java - 如何使用来自 JDBC 连接器的高吞吐量 JAVA I/O 流避免内存溢出?
问题描述
考虑从(wrt 内存)无限源获取有限数量的数据的任务,例如,我需要counts
从包含数十亿和更多条目的巨大表中获取,这些条目由有限但可能巨大的时间窗口标记timestamp
并在其内进行。foreign_key
但是对于以后的消费,我只需要最大值gridSize
。
注意:后备数据库是 MariaDb,我们使用 spring data jpa 连接到数据库。
一种基于流的方法是:
int stepSize = (int) (numberOfCountsInWindow / gridSize) + 1;
StreamUtils
.zipWithIndex(countStream)
.filter(countIndexed -> countIndexed.getIndex() % stepSize == 0)
...
<intermediate steps>
...
.collect(Collectors.toList())
我已经尝试了很多其他方法,例如:
- 一个 custom
Collector
,它使用一个AtromicLong
来决定下一个值是添加到最终列表中还是只是被忽略, - Flux.defere( () -> ),使用 Flux 背压管理
- 爪哇 11
- 大量 MySQL 选项,如“useCursorFetch=true”,结合有限的预取大小
@QueryHint()
- ...
但是,我尝试过的所有方法都会导致GC overhead limit exceeded
(堆大小限制为 2048,这是我们应用程序的默认值)。
原因是,cpu 完全忙于垃圾收集,而内存消耗刚刚填满,直到最终应用程序崩溃。
我真正期望(或至少希望)的是流“实现”过滤并继续实际计算,最多使用 100% cpu,垃圾收集器可以轻松删除未使用的对象,因为它们是无论如何都被过滤掉了,甚至不需要被解析(希望流的懒惰在这里有所帮助)。但是,这似乎并没有像我希望的那样工作。
非常欢迎发表评论或建议,因为我想(至少)理解(最好解决)而不是接受这种情况。
编辑:也欢迎使用 MariaDB 的替代品(也许是 Cassandra?)。
解决方案
推荐阅读
- java - 无法打印出 b.toString 和 c.toString
- terminal - graphviz 安装失败
- loops - 用 ansible 创建字典
- r - 将 mm-yy 字符串转换为 R 中的日期
- configuration - HxCPP 添加包含路径和链接器选项
- php - 语法错误,意外的 'endforeach' (T_ENDFOREACH),期待 elseif (T_ELSEIF) 或 else (T_ELSE) 或 endif (T_ENDIF)
- flutter - 为什么 Jiffy 包显示错误的周数
- d3.js - 如何让这个 D3js 旭日形图显示所有层的数据?
- scala - Scala 将 Map[String, Int]("a"->2, "b"->1) 转换为 Sequence Seq("a", "a", "b")
- jenkins - Jenkins Multibranch Pipeline:区分由分支索引触发的构建与 webhook