为了账号安全,请及时绑定邮箱和手机立即绑定

使用Hibernate的ScrollableResults缓慢读取9000万条记录

使用Hibernate的ScrollableResults缓慢读取9000万条记录

慕雪6442864 2019-12-25 15:57:48
我只需要使用Hibernate读取MySQL数据库中表中的每一行,并基于它编写一个文件。但是有9000万行,它们很大。因此,似乎以下情况将是适当的:ScrollableResults results = session.createQuery("SELECT person FROM Person person")            .setReadOnly(true).setCacheable(false).scroll(ScrollMode.FORWARD_ONLY);while (results.next())    storeInFile(results.get()[0]);问题是上面的方法将尝试将所有9000万行加载到RAM中,然后再进入while循环...这将导致OutOfMemoryError杀死我的内存:Java堆空间异常:(。所以我想ScrollableResults不是我想要的吗?处理此问题的正确方法是什么?我不在乎这个while循环是否需要几天的时间(好吧,我不希望这样)。我猜想解决此问题的唯一其他方法是使用setFirstResult和setMaxResults遍历结果,并且仅使用常规的Hibernate结果而不是ScrollableResults。感觉好像效率低下,并且当我在第89百万行上调用setFirstResult时,它将花费可笑的长时间。更新:setFirstResult / setMaxResults不起作用,事实证明我花了很长的时间才能达到我所担心的偏移量。这里一定有解决方案!这不是一个很标准的程序吗?我愿意放弃Hibernate并使用JDBC或其他方法。更新2:我想出的可行的解决方案,不是很好,基本上是以下形式:select * from person where id > <offset> and <other_conditions> limit 1由于我还有其他条件,即使所有条件都在索引中,它仍然不如我希望的那样快...因此仍然欢迎其他建议。
查看完整描述

3 回答

?
一只萌萌小番薯

TA贡献1795条经验 获得超7个赞

如下所示,将查询中的抓取大小设置为最佳值。


同样,当不需要缓存时,最好使用StatelessSession。


ScrollableResults results = session.createQuery("SELECT person FROM Person person")

        .setReadOnly(true)

        .setFetchSize( 1000 ) // <<--- !!!!

        .setCacheable(false).scroll(ScrollMode.FORWARD_ONLY)


查看完整回答
反对 回复 2019-12-25
  • 3 回答
  • 0 关注
  • 784 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信