2

我们运行的一些查询有 100,000 多个结果,加载它们然后将它们发送到客户端需要很长时间。所以我使用 ScrollableResults 来获得分页结果功能。但是我们以大约 50k 个结果(从不完全相同数量的结果)达到顶峰。

我在 Oracle9i 数据库上,使用 Oracle 10 驱动程序,Hibernate 配置为使用 Oracle9 方言。我尝试使用最新的 JDBC 驱动程序 (ojdbc6.jar) 并重现了问题。

我们也遵循了一些建议并添加了一个排序条款,但问题被重现了。

这是一个代码片段,说明了我们的工作:

final int pageSize = 50;
Criteria crit = sess.createCriteria(ABC.class);
crit.add(Restrictions.eq("property", value));
crit.setFetchSize(pageSize);
crit.addOrder(Order.asc("property"));
ScrollableResults sr = crit.scroll();
...
...
ArrayList page = new ArrayList(pageSize);
do{
  for (Object entry : page)
    sess.evict(entry); //to avoid having our memory just explode out of proportion
  page.clear();
  for (int i =0 ; i < pageSize && ! metLastRow;  i++){
    if (sr.next())
      page.add(sr.get(0));
    else 
      metLastRow = true;
  }
  metLastRow = metLastRow?metLastRow:sr.isLast();

  sendToClient(page);
}while(!metLastRow);

那么,为什么我得到的结果集在最后告诉我它什么时候应该有更多的结果呢?

4

2 回答 2

1

您的代码片段缺少重要部分,例如 和 的resultSet定义page。但我想知道无论如何,不​​应该行

if (resultSet.next())

宁可

if (sr.next())

?

作为旁注,AFAIK 从持久性上下文中清理多余的对象可以简单地通过调用来实现

session.flush();
session.clear();

而不是循环遍历对象集合以分别逐出每个对象。(当然,这要求查询在其自己的独立会话中执行。)

更新:好的,下一轮猜测:-)

你能真正检查哪些行发送到客户端,并将其与直接针对数据库的等效 SQL 查询的结果进行比较吗?很高兴知道此代码是否检索(并将所有行发送到客户端,直到某个限制,或者仅从整个结果集中检索一些行(如每 2 行),或者......这可以阐明根原因。

您可以尝试的另一件事是

crit.setFirstResults(0).setMaxResults(200000);
于 2010-04-05T12:14:27.453 回答
1

由于我在基于List<E>实例的大型项目代码中遇到了同样的问题,因此我编写了一个非常有限的 List 实现,仅支持迭代器来浏览 ScrollableResults,而无需重构所有服务实现和方法原型。

这个实现在我的IterableListScrollableResults.java Gist中可用

它还定期从会话中刷新 Hibernate 实体。这是一种使用它的方法,例如,当从 DB 中将所有非归档实体导出为带有for循环的文本文件时:

Criteria criteria = getCurrentSession().createCriteria(LargeVolumeEntity.class);
criteria.add(Restrictions.eq("archived", Boolean.FALSE));
criteria.setReadOnly(true);
criteria.setCacheable(false);
List<E> result = new IterableListScrollableResults<E>(getCurrentSession(),
        criteria.scroll(ScrollMode.FORWARD_ONLY));
for(E entity : result) {
    dumpEntity(file, entity);
}

希望它可能会有所帮助

于 2014-04-01T13:57:18.383 回答