【问题标题】:Read SQL Database in batches批量读取 SQL 数据库
【发布时间】:2013-05-18 22:50:10
【问题描述】:

我正在使用Java 读取SQL RDBMS 并将结果返回给用户。问题是数据库表有155 Million rows,这使得等待时间很长。

我想知道是否有可能从数据库中检索结果并以增量方式(分批)将它们呈现给用户。

我的查询是一个简单的SELECT * FROM Table_Name query

有没有一种机制或技术可以让我批量回调数据库记录,直到SELECT 查询完成?

使用的 RDBMS 是 MS SQL Server 2008。

提前致谢。

【问题讨论】:

  • 您是否要一次将所有 1.55 亿行返回给最终用户?
  • 根据 RDBMS 仅选择有限的行数,MySql 使用 Limit 用于 Sql Server 使用 TOP n
  • +1 以上评论。用户可以用 1.55 亿行有意义地做什么?另外,哪个数据库? JDBC “支持”在StatementResultSet 中设置要获取的行数。不幸的是,这些不一定根据您的 JDBC 供应商实现,
  • @Woot4Moo 确实,我需要返回所有 155 M 行。
  • 我唯一的建议是找到一种在服务器上实现大部分功能的方法。 RDBMS 是为此类任务设计的(并且希望是优化的)。如果不止一个查询,那么考虑存储过程。

标签: java sql sql-server-2008 jdbc


【解决方案1】:

方法Statement#setFetchSizeStatement#getMoreResults 应该允许您管理从数据库中获取的增量。不幸的是,这是接口规范,供应商可能会也可能不会实现这些。获取期间的内存管理实际上取决于供应商(这就是为什么我不会严格地说“JDBC 就是这样工作的”)。

来自JDBC documentation on Statement

setFetchSize(int rows)

给 JDBC 驱动程序一个关于应该是多少行的提示 当 ResultSet 需要更多行时从数据库中获取 此语句生成的对象。

getMoreResults()

移动到这个Statement对象的下一个结果,如果是一个返回true ResultSet 对象,并隐式关闭任何当前的 ResultSet 对象 用getResultSet方法获取。

getMoreResults(int current)

移动到此 Statement 对象的下一个结果,处理任何当前 根据给定指令指定的 ResultSet 对象 标志,如果下一个结果是 ResultSet 对象,则返回 true。 current param表示保持或关闭当前ResultSet?

此外,这个SO response 回答了关于在 SQLServer 2005 中使用setFetchSize 以及它似乎不管理批量提取的问题。建议使用 2008 驱动程序进行测试,或者,使用 jTDS 驱动程序(在 cmets 中获得好评)

这个response to the same SO post 也可能很有用,因为它包含指向 MSDN 上的 SQLServer 驱动程序设置的链接。

the MS technet website 上也有一些很好的信息,但更多地与 SQLServer 2005 相关。在我粗略的回顾中找不到 2008 特定版本。无论如何,它建议创建语句:

com.microsoft.sqlserver.jdbc.SQLServerResultSet.TYPE_SS_SERVER_CURSOR_FORWARD_ONLY (2004) 可滚动性用于只进、只读访问,然后使用 setFetchSize 方法调整性能

【讨论】:

    【解决方案2】:

    这正是 JDBC 驱动程序应该如何工作的(我记得旧 PostgreSQL 驱动程序中的错误,它导致所有获取的记录都存储在内存中)。

    但是,它使您能够在查询开始获取记录时读取记录。这就是我要开始搜索的地方。

    例如,Oracle 优化了SELECT * 查询以获取整个集合。这意味着可能需要很长时间才能出现第一个结果。您可以提供提示以优化获取第一个结果,这样您就可以非常快速地向用户显示第一行,但整个查询可能需要更长的时间来执行。

    您应该首先在控制台上测试您的查询,以检查它何时开始获取结果。然后尝试使用 JDBC 并在迭代 ResultSet 时监控内存使用情况。如果内存使用量增长很快,请检查您是否以只进和只读模式打开了 ResultSet,如有必要更新驱动程序。

    如果这种解决方案由于内存使用不可行,您仍然可以手动使用游标并在每个查询中获取 N 行(例如 100 行)。

    MSSQL 的光标文档:例如这里:http://msdn.microsoft.com/en-us/library/ms180152.aspx

    【讨论】:

    • 感谢您的回答。我猜这个 MS 游标和获取功能应该可以完成这项工作。我会试一试并发布任何结果。
    【解决方案3】:

    使用分页 (LIMIT pageno, rows / TOP) 可能会产生漏洞和重复,但可能与检查最后一行 ID (WHERE id > ? ORDER BY id LIMIT 0, 100) 结合使用。

    您可以使用TYPE_FORWARD_ONLYFETCH_FORWARD_ONLY

    【讨论】:

      猜你喜欢
      • 2018-06-07
      • 2016-09-27
      • 2016-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-04
      • 2020-06-28
      • 1970-01-01
      相关资源
      最近更新 更多