我正在尝试使用JDBC从数据库创建转储文件。该文件应该是大约300 MB的大小,包含十列中的1.2到1.5百万条记录,但我的内存耗尽大约25万。
我的问题是java将整个记录集存储在内存中吗?我已经将记录集设置为只能向前读取,希望已经转储的记录将从内存中清除,但似乎并非如此。
非常感谢任何帮助。
答案 0 :(得分:7)
您应该在setFetchSize
对象上使用Statement
。以下示例一次仅从ResultSet
:
Connection con = DriverManager.getConnection("jdbc:my_subprotocol:my_subname");
Statement stmt = con.createStatement();
stmt.setFetchSize(1000);
ResultSet rs = stmt.executeQuery("SELECT * FROM your_table");
这是Javadoc:
http://java.sun.com/javase/6/docs/api/java/sql/Statement.html#setFetchSize(int)
答案 1 :(得分:1)
如果您正在检索所有数据,然后作为第二步写入文件,那么所有数据库数据都将存储在内存中。如果您将数据流式传输到文件,则不会发生这种情况。即,而不是
data=...
while (rs.next()){
... add rs value to data
}
..write data to file
类似
file=...
while (rs.next()){
write rs to file
}
答案 2 :(得分:0)
获取缓冲区/释放行为取决于JDBC驱动程序以及JVM的垃圾收集器。在写入FileOutputStream之前,您是否正在进行任何缓冲(这可能会阻止您的内存被垃圾回收)?
尝试使用-Xms
和-Xmx
java运行时参数调整Java堆大小。示例:
java -Xms1024M -Xmx1024M com.mypkg.MyResultSetReader
上面的命令将为您的程序提供1GB的堆空间。如果这是一个临时工具,或者您不希望ResultSet大小增长,则可以将其作为永久解决方案。
答案 3 :(得分:0)
设置fetchSize应该会有所帮助。但实际上它取决于jdbc驱动程序。但是你可以迭代地(通过一小部分)读取数据:
stm = conn.prepareStatement("...where id > ? order by id");
stm.setMaxRows(100);
while(true) {
stm.setInt(1, lastId);
ResultSet results = stm.executeQuery();
// process results and assign a new value to lastId
rs.close();
}