3

问题:如何一次处理(读入)1000 条记录的批次,并确保只有当前批次的 1000 条记录在内存中?假设我的主键被称为 ' ID' 并且我的表被称为Customer

背景:这不是用于用户分页,而是用于编译有关我的表的统计信息。我的可用内存有限,因此我想一次读取 1000 条记录的记录。我只是在阅读记录,它们不会被修改。我读过这StatelessSession对这种事情有好处,而且我听说过人们使用ScrollableResults.

我尝试过的:目前我正在开发一个定制的解决方案,在该解决方案中我实现了 Iterable 并且基本上使用setFirstResultand进行了分页setMaxResults。这对我来说似乎很慢,但它允许我一次获得 1000 条记录。我想知道如何更有效地做到这一点,也许使用类似ScrollableResults. 我还不确定为什么我目前的方法这么慢;我按 ID 排序,但 ID 是主键,所以表应该已经被索引了。

正如您可能会说的,我一直在阅读有关如何执行此操作的点点滴滴。如果有人可以为我提供一个完整的方法来做到这一点,将不胜感激。我确实知道您必须设置并且调用会将实体从内存FORWARD_ONLY中取出(除非您正在执行二级缓存,我还不知道如何检查我是否存在)。但是,我在 JavaDoc 中看不到任何方法可以一次读取 1000 条记录。我希望在可用内存不足和网络性能缓慢之间取得平衡,因此一次通过网络发送一条记录真的不是这里的选择。我尽可能使用 Criteria API。感谢任何详细的答复。ScrollableResultsevict(entity)

4

2 回答 2

1

May useing of ROWNUM feature of oracle will hepl you.
Lets say we need to fetch 1000 rows(pagesize) of table CUSTOMERS and we need to fetch second page(pageNumber)

Creating and Calling some query like this may be the answer

select * from 
  (select rownum row_number,customers.* from Customer 
   where rownum <= pagesize*pageNumber order by ID)
where row_number >= (pagesize -1)*pageNumber
于 2013-03-15T19:25:53.410 回答
0
  1. 以只读方式加载实体。

    对于 HQL

    Query.setReadOnly( true );
    

    对于标准

    Criteria.setReadOnly( true );
    

    http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/readonly.html#readonly-api-querycriteria

    Stateless session 与 State-Session 完全不同。

    使用无状态会话执行的操作永远不会级联到关联的实例。无状态会话忽略集合

    http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/batch.html#batch-statelesssession

  2. 使用 flash() 和 clear() 清理会话缓存。

    session.flush();

    session.clear();

    关于 Hibernate session.flush() 的问题

  3. ScrollableResults 应该如您所愿。

    不要忘记您加载的每个项目都会占用内存空间,除非您驱逐或清除并需要检查它是否真的运行良好。

    Mysql J/Connecotr 中的 ScrollableResults 是假的,它会加载整行,但我认为 oracle 连接器工作正常。

    Using Hibernate's ScrollableResults to slowly read 90 million records

    If you find alternatives, you may consider to use this way

    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
    
于 2013-03-15T04:24:35.067 回答