jdbc +大的postgresql查询给出内存不足

kre*_*jer 10 java jdbc

我正在尝试执行一个返回大结果的postgresql查询:

connection.setAutoCommit(false);
st = connection.createStatement(
  ResultSet.CONCUR_READ_ONLY,
  ResultSet.TYPE_FORWARD_ONLY
);
st.setFetchSize(100);
logMemory();
System.out.println("start query ");
rs = st.executeQuery(queryString);
System.out.println("done query ");
logMemory();
Run Code Online (Sandbox Code Playgroud)

但这会占用大量内存:

Free memory; 4094347680  (= 3905 mb).
start query 
done query
Free memory; 2051038576  (= 1956 mb).
Run Code Online (Sandbox Code Playgroud)

(使用Runtime.getRuntime()打印.freeMemory())

到目前为止,它的工作原理,但数据库将会更大.我不需要记忆中的整个结果; 我只需要处理每一行,将结果写入磁盘并转到下一行.

我知道'setFetchSize'只是一个提示,但是如果postgresql/jdbc会忽略它,我会觉得很奇怪,因为它已经存在了很长时间.

有办法解决这个问题吗?到目前为止,我唯一的想法是创建一个批处理脚本,将查询结果流式传输到磁盘,然后从Java解析文件...

Yis*_*hai 13

以下是确保使用游标实际检索结果集的准则.你好像在你的代码中遇到了所有已知的那些,但是你还没有指定语句,所以它可能是几个用分号串联起来的(不太可能,你的代码的外观).您必须使用V3协议(版本7.4或更高版本).所有这些都适用于您的情况吗?

  • 非常感谢你的回答.我一整天都在努力解决这个问题,直到我在你引用的页面上找到了`conn.setAutoCommit(false)`的要求. (2认同)

Fra*_*aar 8

哎呀,这是我见过的最讨厌的错误之一.你应该改变

st = connection.createStatement(
  ResultSet.CONCUR_READ_ONLY,
  ResultSet.TYPE_FORWARD_ONLY
);
Run Code Online (Sandbox Code Playgroud)

st = connection.createStatement(
  ResultSet.TYPE_FORWARD_ONLY,
  ResultSet.CONCUR_READ_ONLY
);
Run Code Online (Sandbox Code Playgroud)

也许只是

st = connection.createStatement();
Run Code Online (Sandbox Code Playgroud)

也会工作(因为你已经满足了游标的其他标准).