【问题标题】:Unable to fetch result set in Batches using ScrollableResults无法使用 ScrollableResults 批量获取结果集
【发布时间】:2021-05-19 15:26:45
【问题描述】:

我需要从 Postgres 数据库表中过滤掉数据。该查询可以返回数百万个数据,因此无法将数据保存在内存中,因为它会导致 OOME。我尝试使用 ScrollableResult 来批量获取数据,但如在 logs 中看到的那样,正在触发单个查询。下面的sn -p是用来生成的。

@Transactional
public void getObjectUsingScrollable() {
    String statement = "select t1.name,t2.address from table1 t1 JOIN table2 t2 ON t1.id=t2.table1Id WHERE t1.status='OPEN' ORDER BY t1.date DESC "
    StatelessSession session = ((Session) entityManager.getDelegate()).getSessionFactory().openStatelessSession();
    org.hibernate.query.Query query = session
            .createNativeQuery(statement);
    query.setFetchSize(5);
    query.setReadOnly(true);
    query.setLockMode("t1", LockMode.READ);
    query.setCacheable(false);
    ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);
    while (results.next()) {
        Object obj=results.get(0);
    }
    results.close();
    session.close();
}

我尝试过使用 LockMode.NONE 。 为什么在 while 循环的每 5 次迭代后不会触发查询? 休眠版本 - 5.4.18 Postgres 版本 - 9.4-1200-jdbc41

【问题讨论】:

  • 可能是由于 query.setFetchSize(5) 行?尝试更改为 10 并检查。
  • @Alien 我尝试使用以下 fetchSize 值。 5,50,500。
  • 好的.. postgres 控制台返回多少行普通 sql 查询?
  • @Alien 5630 行。

标签: hibernate jpa spring-data-jpa spring-data entitymanager


【解决方案1】:

这不是可滚动结果的工作方式,您只会看到一个查询。获取大小只是 JDBC 驱动程序每次往返数据库仅获取那么多行的提示。

本质上,可滚动结果就像数据库上的打开游标,您可以在其中获取 N(获取大小)元素。驱动程序为您提供这些行,当您请求更多时,它可能会通过游标获取接下来的 N 行。

使用您显示的代码,除非您将数据保存在某个地方,否则您不应该得到 OOME。至少 Hibernate 不会以这种方式保存数据。

【讨论】:

  • 感谢您的解释。而如果第二次往返DB出现异常,会不会打开游标释放DB连接。因为我有时会遇到一个问题,即 Hikari 池已用尽。 results.next() 抛出 NullPointerException 。相同的 sql 查询返回 DB 中的数据,但 results.next() 仍然抛出 NPE。在此异常之后,对同一方法的第二次调用会抛出 Hikari 池已耗尽的异常。
  • 我不知道你的代码是做什么的,但是如果你不关闭连接(注意像Hikari这样的连接池通常会返回一个连接代理),它不会返回连接水池。如果您遇到异常并忘记关闭资源,则连接可能会丢失。你可能需要try { ... } finally { session.close(); }
猜你喜欢
  • 2011-02-04
  • 1970-01-01
  • 2012-04-30
  • 1970-01-01
  • 2013-06-13
  • 1970-01-01
  • 1970-01-01
  • 2015-10-03
相关资源
最近更新 更多