从大表读取时的java.lang.OutOfMemoryError

Maj*_*imi 3 java jdbc out-of-memory

我正在尝试从PostgreSQL中的一个非常大的表(300GB)预生成报告.我做这样的事情:

rs = stmt.executeQuery("SELECT * FROM tbl");
System.out.println("select all finished");
while (rs.next()) {
    /* generate report and save it in report table */
    /* generated reports are not in memory, 
     * They are saved in a summary table in each iteration */
}
Run Code Online (Sandbox Code Playgroud)

当我启动应用程序时,它给出了Exception in thread "main" java.lang.OutOfMemoryError: Java heap space.我尝试使用stmt.setFetchSize(1000)但它没有解决问题.

解决办法是什么?我在Debian 6.0.5和openJDK 6上使用PostgreSQL 8.4.11.

[UPDATE]

打印的堆栈跟踪显示OutOfMemoryError异常已rs = stmt.executeQuery("SELECT * FROM tbl");在行中生成.也System.out.println("select all finished");永远不会显示.

  1. 我正在以autocommit模式运行.
  2. stmt.getResultSetConcurrency() 返回1007.
  3. stmt.getResultSetHoldability() 返回2.
  4. rs.getType() 返回1003.

Mar*_*eel 8

问题可能是PostgreSQL仅fetchSize在一小部分情况下使用.请参阅:http://jdbc.postgresql.org/documentation/91/query.html#fetchsize-example

  • 与服务器的连接必须使用V3协议.这是服务器版本7.4及更高版本的默认设置(仅受支持).
  • Connection不能处于自动提交模式.后端在事务结束时关闭游标,因此在自动提交模式下,后端将关闭游标,然后才能从中获取任何内容.
  • 必须使用ResultSet类型ResultSet.TYPE_FORWARD_ONLY创建Statement.这是默认值,因此不需要重写代码以利用此功能,但这也意味着您无法向后滚动或以其他方式在ResultSet中跳转.
  • 给出的查询必须是单个语句,而不是与分号串在一起的多个语句.

因此,如果您在自动提交中执行此操作,或者使用TYPE_FORWARD_ONLYPostgreSQL 以外的结果集类型将获取所有行.另外看一下PostgreSQL JDBC 9.0-801驱动程序的来源,看起来使用一个可保持的结果集也会使它获取所有行.