Java 为什么我的Postgres光标内存不足?
我有一个巨大的表,我正试图流到一个文件。然而,似乎无论我怎么做,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
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而不是简单的语句。有人知道吗?不管怎样,我已经克服了这个障碍。谢谢你的洞察力,马尔科!