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

时间:2009-10-01 14:36:38

标签: 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();

但这会占用大量内存:

Free memory; 4094347680  (= 3905 mb).
start query 
done query
Free memory; 2051038576  (= 1956 mb).

(使用Runtime.getRuntime()。freeMemory())

打印

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

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

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

2 个答案:

答案 0 :(得分:12)

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

答案 1 :(得分:7)

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

st = connection.createStatement(
  ResultSet.CONCUR_READ_ONLY,
  ResultSet.TYPE_FORWARD_ONLY
);

st = connection.createStatement(
  ResultSet.TYPE_FORWARD_ONLY,
  ResultSet.CONCUR_READ_ONLY
);

也许只是

st = connection.createStatement();

也可以正常工作(因为你已经满足了游标的其他标准)。