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

时间:2009-05-13 16:04:24

标签: java database jdbc

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

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

如果我有一个包含一百万条记录的ResultSet但我的表只显示ResultSet中前十条记录中的数据,那么只有当我开始请求记录数据或者所有数据完全加载到内存中时才会获取数据一旦从执行SQL语句返回ResultSet?

5 个答案:

答案 0 :(得分:39)

Java ResultSet是数据库中结果的指针(或游标)。 ResultSet从数据库中加载块中的记录。因此,要回答您的问题,只有在您提出请求时才会获取数据。

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

答案 1 :(得分:10)

JDBC规范未指定数据是否已流式传输或是否已加载到内存中。默认情况下是Oracle流。 MySQL没有。要让MySQL流式传输结果集,您需要在Statement:

上设置以下内容
    pstmt = conn.prepareStatement(
        sql,
        ResultSet.TYPE_FORWARD_ONLY,
        ResultSet.CONCUR_READ_ONLY);
    pstmt.setFetchSize(Integer.MIN_VALUE);

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:0)

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

要创建子查询,您可以在oracle中使用行计数,在MY SQL中使用Limit。

答案 4 :(得分:0)

假设我们有一个包含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