Java 为什么我的Postgres光标内存不足?

Java 为什么我的Postgres光标内存不足?,java,postgresql,out-of-memory,database-cursor,Java,Postgresql,Out Of Memory,Database Cursor,我有一个巨大的表,我正试图流到一个文件。然而,似乎无论我怎么做,Postgres都试图一次提取所有数据并耗尽内存。我在这里和其他地方读过很多帖子,我认为我做的是“正确的”,那么为什么我总是没有足够的内存呢 这是我的密码: Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword); conn.setAutoCommit(false); conn.setReadO

我有一个巨大的表,我正试图流到一个文件。然而,似乎无论我怎么做,Postgres都试图一次提取所有数据并耗尽内存。我在这里和其他地方读过很多帖子,我认为我做的是“正确的”,那么为什么我总是没有足够的内存呢

这是我的密码:

        Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword);

        conn.setAutoCommit(false);
        conn.setReadOnly(true);

        Statement ps = conn.createStatement(
                ResultSet.TYPE_FORWARD_ONLY, 
                ResultSet.CONCUR_READ_ONLY, 
                ResultSet.HOLD_CURSORS_OVER_COMMIT);

        ps.setFetchSize(10);

        String sql = "SELECT * FROM BIGTABLE "
             + "WHERE '20150401' BETWEEN startdate AND enddate";

        ResultSet rs = ps.executeQuery(sql);

        writeResultSet(os, rs);
在内存不足之前,代码永远不会通过查询执行

如果有关系,这是在一个单独的线程中发生的,而流式传输到一个开放的ZipOutputStream。在这一点上,一个项目已经流出来了,我从来没有达到我可以流出来这张表的程度

我正在使用Postgres9.3.5,目前将虚拟机的测试限制在128MB。虽然我可以增加堆的大小,但我仍然认为我不应该遇到这个问题

[jsyk,为了清晰起见,我去掉了try/catch块等。]

ResultSet.HOLD_CURSORS_OVER_COMMIT
此设置要求一个可保持的游标,该游标是为Postgresql在客户端实现的。Postgresql本身不支持JDBC使用的协议(前端/后端协议)上的本机可持有游标。相关职位:

还要注意,即使本机可保持游标也需要O(n)空间,但它将在磁盘上进行分配


但是,通过查看您的代码,我看不出您需要一个可保持光标的原因。

128MB的内存量非常小,一个大型查询肯定会超过Java的内存限制。你试过分配更多的内存吗?另外,您可以发布完整的错误消息吗。@adam OP正在使用较小的内存限制来加快测试失败的速度。他的意图是实现O(1)空间要求,较小的堆限制将更敏感地检测O(n)空间。感谢关于可保持光标的信息。我听到一个错误,听起来好像我的连接正在关闭,所以我打开了它。但我刚刚删除了它,我不再耗尽内存!事实上,它看起来非常健忘。我想知道我之前遇到的问题是否是由于使用了PreparedStatement而不是简单的语句。有人知道吗?不管怎样,我已经克服了这个障碍。谢谢你的洞察力,马尔科!