【问题标题】:Does a ResultSet load all data into memory or only when requested?ResultSet 是将所有数据加载到内存中还是仅在请求时加载?
【发布时间】:2010-10-25 22:07:51
【问题描述】:

我有一个 .jsp 页面,其中有一个显示 Oracle 数据库记录的 GUI 表。该表允许典型的分页行为,例如“FIRST”、“NEXT”、“PREVIOUS”和“LAST”。记录是从执行 SQL 语句返回的 Java ResultSet 对象中获取的。

这个 ResultSet 可能很大,所以我的问题是:

如果我有一个包含 100 万条记录的 ResultSet,但我的表只显示 ResultSet 中前十条记录的数据,是仅在我开始请求记录数据时才获取数据,还是所有数据都完全加载到内存中一旦执行 SQL 语句返回 ResultSet?

【问题讨论】:

    标签: java database jdbc


    【解决方案1】:

    Java ResultSet 是指向数据库中结果的指针(或游标)。 ResultSet 从数据库中加载块中的记录。因此,为了回答您的问题,数据仅在您请求时获取,但以块的形式获取。

    如果您需要控制驱动程序一次获取多少行,您可以使用 ResultSet 上的setFetchSize(int rows) 方法。这将允许您控制一次检索的块的大小。

    【讨论】:

    • MySql 驱动(mysql-connector-j)是否支持这种“智能”行为?
    • @Roman JDBC API 并不表示它是可选方法。我会假设包括 mysql 在内的所有实现都支持这一点。
    • 如果“所有实现都支持”,那么 JDBC-ODBC 桥如何为 MS Access 做到这一点? Access 不支持“限制”或类似的东西,是吗?
    • 获取大小基本上是对驱动程序在给定时间获取多少记录的“建议”,并且由驱动程序决定是使用建议的大小还是忽略它。我想大多数设计良好的驱动程序都会使用它。 jTDS(用于 SQL Server)使用它。
    • 不错的答案+1。我们能否获得有关此行为的文档参考?
    【解决方案2】:

    JDBC 规范没有指定数据是流式传输还是加载到内存中。默认情况下,Oracle 流。 MySQL 没有。要让 MySQL 流式传输结果集,您需要在 Statement 上设置以下内容:

        pstmt = conn.prepareStatement(
            sql,
            ResultSet.TYPE_FORWARD_ONLY,
            ResultSet.CONCUR_READ_ONLY);
        pstmt.setFetchSize(Integer.MIN_VALUE);
    

    【讨论】:

    • 我想知道 MYSQL 8 是否有任何更新
    【解决方案3】:

    虽然 JDBC 规范没有指定是否要获取结果集中的所有数据,但任何编写良好的驱动程序都不会这样做。

    也就是说,可滚动的结果集可能更符合您的想法: (链接已编辑,它指向一个间谍软件页面)

    您还可以考虑存储在会话中的断开连接的行集(取决于您的网站需要的可扩展性): http://java.sun.com/j2se/1.4.2/docs/api/javax/sql/RowSet.html

    【讨论】:

    • 仅供参考:exampledepot.com 抛出“硬盘需要碎片化”警告消息。
    【解决方案4】:

    最好的办法是进行子查询并一次/在单页中显示 100 或 1000 行。并通过连接池管理连接。

    要进行子查询,您可以在 oracle 中使用 Row count 并在 MY SQL 中使用 Limit。

    【讨论】:

      【解决方案5】:

      假设我们有一个包含 500 条记录的表

      PreparedStatement stm=con.prepareStatement("select * from table");
      stm.setFetchSize(100);// now each 100 records are loaded together from the database into the memory,
      // and since we have 500 5 server round trips will occur.
      ResultSet rs = stm.executeQuery();
      rs.setFetchSize (50);//overrides the fetch size provided in the statements,
      //and the next trip to the database will fetch the records based on the new fetch size
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-17
        • 2014-02-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-04
        相关资源
        最近更新 更多