ResultSet 是将所有数据加载到内存中还是仅在请求时加载?

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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

【讨论】:

以上是关于ResultSet 是将所有数据加载到内存中还是仅在请求时加载?的主要内容,如果未能解决你的问题,请参考以下文章

将 CSV 从 GCS 批量加载到 BigQuery 时,表数据是增量查看还是仅在所有文件加载后才可查看?

如何仅从 ResultSet 中获取第一行

如何使用带有 Spring RowMapper 的 RowSetDynaClass 来检索 ResultSet 的所有行?

get(replicated)map加载整个数据还是只是加载引用?

PowerQuery“加载”命令详解

ldc