问题:如何一次处理(读取)成批的1000条记录,并确保仅当前的1000条记录在内存中?假设我的主键叫'ID
',而我的表叫Customer
。
背景:这不是用于用户分页,而是用于编译有关我的表的统计信息。我的可用内存有限,因此我想一次读取1000条记录中的记录。我只读记录,不会被修改。我已经读到StatelessSession
对于这种事情有好处,而且我听说有人在使用ScrollableResults
。
我尝试过的工作:目前,我正在开发一个定制解决方案,在该解决方案中我实现了Iterable,并且基本上使用setFirstResult
和setMaxResults
进行了分页。这对我来说似乎很慢,但是它一次可以获取1000条记录。我想知道如何使用ScrollableResults
之类的方法更有效地做到这一点。我还不确定为什么我现在的方法这么慢?我正在按ID排序,但是ID是主键,因此该表应该已经被索引了。
如您所知,我一直在阅读有关如何执行此操作的点点滴滴。如果有人可以为我提供完成此操作的完整方法,将不胜感激。我确实知道您必须在FORWARD_ONLY
上设置ScrollableResults
,并且调用evict(entity)
将使一个实体耗尽内存(除非您正在执行二级缓存,但我尚不知道如何检查我是否在或不)。但是我看不到JavaDoc中的任何方法可以一次读取1000条记录。我希望在缺乏可用内存和网络性能较慢之间取得平衡,因此实际上一次不能通过网络发送记录。我在可能的情况下使用Criteria API。感谢您的详细回复。
最佳答案
将实体加载为只读。
对于HQL
Query.setReadOnly( true );
对于标准
Criteria.setReadOnly( true );
http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/readonly.html#readonly-api-querycriteria
无状态会话与State-Session完全不同。
使用无状态会话执行的操作永远不会级联到关联的实例。无状态会话会忽略集合
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html#batch-statelesssession
使用flash()和clear()清理会话缓存。
session.flush();
session.clear();
Question about Hibernate session.flush()
ScrollableResults应该可以正常工作。
不要忘记加载的每个项目都会占用内存空间,除非您逐出或清除并需要检查它是否确实工作正常。
Mysql J / Connecotr中的ScrollableResults可以伪造,可以加载整行,但是我认为oracle连接器可以正常工作。
Using Hibernate's ScrollableResults to slowly read 90 million records
如果您找到替代方法,则可以考虑使用这种方式
1. Select PrimaryKey of every rows that you will process
2. Chopping them into PK chunk
3. iterate -
select rows by PK chunk (using in-query)
process them what you want