首页 > 解决方案 > 如何使用来自 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())

我已经尝试了很多其他方法,例如:

但是,我尝试过的所有方法都会导致GC overhead limit exceeded(堆大小限制为 2048,这是我们应用程序的默认值)。

原因是,cpu 完全忙于垃圾收集,而内存消耗刚刚填满,直到最终应用程序崩溃。

我真正期望(或至少希望)的是流“实现”过滤并继续实际计算,最多使用 100% cpu,垃圾收集器可以轻松删除未使用的对象,因为它们是无论如何都被过滤掉了,甚至不需要被解析(希望流的懒惰在这里有所帮助)。但是,这似乎并没有像我希望的那样工作。

非常欢迎发表评论或建议,因为我想(至少)理解(最好解决)而不是接受这种情况。

编辑:也欢迎使用 MariaDB 的替代品(也许是 Cassandra?)。

标签: javastreamspring-data-jpagarbage-collection

解决方案


推荐阅读