Java ,大量对象内存中计算, oom 怎么处理哇。

2022-03-20 19:48:24 +08:00
 frank1256

rt ,

遇到个问题,需要查询 100 条记录查到内存中,然后进行计算。我内存很小,总是 oom 。就是单纯的内存不够。有啥好办法吗?

mat 工具打开 dump ,里面全是 mysql 的 jdbc 对象。。。

最高峰 300w 条,也没啥精力再去弄大数据啥的了。老板只给了 8g 。

小弟能想到的就是,分批查询,一批一批计算。靠谱吗?

有什么好办法吗,大佬们

5741 次点击
所在节点    Java
57 条回复
clf
2022-03-21 10:26:36 +08:00
利用磁盘去做缓存。

POI 在操作大数据导出 excel 的时候就是类似的处理方式,一次性只处理 N 行,其余的数据行会在磁盘里利用文件缓存。
leonme
2022-03-21 11:04:06 +08:00
@heyjei #4 这是认真的吗?如果是 OLTP 呢?
liuxingdeyu
2022-03-21 11:14:39 +08:00
我觉得分批查靠谱,再就是活用 mapreduce
cheng6563
2022-03-21 11:21:43 +08:00
楼上这么多人就没个说增加 jvm 内存容量限制的吗?
jvm 默认给的堆内存大小为物理内存的 1/4 ,所以啥不管直接加物理内存的收益也只有 1/4
启动命令用 -Xmx6g 参数可以分配 6g 内存给堆。
堆内存一般占 jvm 进程内存的大多数但不是 100%,所以最好再开些 swap 避免占满内存。
ragnaroks
2022-03-21 13:32:07 +08:00
@cheng6563 一般默认这种基础都会,而且楼主说了给了 7G

@frank1256 如果时效性不高就猛拉 swap ,不过都用 java 了还抠硬件资源你们老板也是过分
kingfalse
2022-03-21 14:59:52 +08:00
自己花钱,再加 8 个 G /狗头
feitxue
2022-03-21 15:41:55 +08:00
也给几个方向,不一定靠谱.要根据你的实际需求来.
第一种,就是你有提到一个月才跑一次的任务的话,那就每天跑一次,生成你要的日数据,月底的时候汇总这一个月每天的数据.或者安排的没人用系统的时候,凌晨,和其他任务错开执行.
第二种,还是你之前代码,不动,月底的时候申请按量计费的机器,跑完就销毁.不确定你们允不允许这样玩儿,不过这种方式可能对 java 不太友好.或者用云函数,现在有支持 java 的,只是改造成本确实有点大.
其他的 sql 优化的楼上都提到了,我就没啥补充了.
vacuitym
2022-03-21 16:29:51 +08:00
我觉得这个应该定期汇总。数据不多的话每天做日统计,多的话做几小时的统计。然后做月统计。最后只要根据统计的数据再做计算就可以了,我们一般这样做
fuchaofather
2022-03-21 16:46:34 +08:00
信息太少了。第一感觉没有必要查 100w 条数据到内存,都是真正需要的吗?
timsims
2022-03-21 16:58:59 +08:00
xxx 量级数据找 top10 这种不就是经典的面试题。。
CaptainD
2022-03-21 18:40:10 +08:00
必须要所有数据同时在内存么,如果不需要是否可以分批计算
sampeng
2022-03-21 18:56:27 +08:00
300w 条记录求平均值,top10.。不都是标准面试算法么。。面试会,实现需求就不会了?
300w 就要上 hadoop 了? 300w 就要大数据了? 300w 哪怕上个 es 也比大数据强啊。。当然,这个量级都不需要。直接硬算酒可以了

1 。分而治之当然靠谱,把数据写入 n 个小文件,再对小文件统计,最后汇总。这一个做法缺点是对数据库压力这个时候会相对较大,如果你的服务器和数据库之间的带宽就 1000M 。会瞬间打满,所以可能会影响业务。
2.limit 控制条目数,开线程内存里去算了然后汇总。坏处是代码写起来复杂,维护相对较麻烦。过了半年可能看不懂自己写的代码。好处就是你可以控制间隔时间,想快就快想慢就慢。

还一个方式。不要侵占你的业务代码,分析是分析,业务时业务。这是完全两个不同的领域。所以:
写个 python 脚本把数据弄出来。。numpy+pandas 。这个数据量,算起来是慢点,但也没有接受不了的程度。
giiiiiithub
2022-03-21 22:20:29 +08:00
可以考虑下预计算(当然,复杂的话不一定可以
FYFX
2022-03-21 22:56:45 +08:00
统计 30 天记录的维度指标,你这个看着像离线场景啊,用 spark 跑完之后把结果同步到 mysql 或者缓存吧。
Brentwans
2022-03-21 23:33:05 +08:00
100w 数据就把 8G 搞 oom 了,看下数据自身情况吧,是字符串很多,还是数值都是存成对象了。百万级别的数据不算多,8G 还是可以放下的。
如果想省事,直接 spark 单机跑吧,肯定没问题吧。
312ybj
2022-03-22 10:33:18 +08:00
1. 分批+多线程处理
这个速度绝对比单线程快,而且资源稳定。
2. 交给大数据
这玩意就是大数据该做的事,Java 不适合大批量数据处理!!!!!
zhangleshiye
2022-03-22 15:10:10 +08:00
如果想在代码里处理的话 ,可以弄张同步中间表,
100w 数据 好比是未经过处理的数据 ->转到中间表(根据各种数据维度 比如时间 一个月处理一个月处理 把这些增量放到中间表里) ,就加一张配置表 比如记录到更新到某某某月了, ->结果就 sum 一下就好了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/841680

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX