我正在尝试使用 JDBC 从数据库创建转储文件。该文件的大小应约为 300 mb,包含 10 列中的 1.2 到 150 万条记录,但我在大约 250000 处内存不足。
我的问题是 java 是否将整个记录集存储在内存中?我已将记录集设置为只能向前读取,希望已转储的记录将从内存中清除,但似乎并非如此。
任何帮助将不胜感激。
您应该setFetchSize
在Statement
对象上使用。以下示例一次只能从 a 获取 1000 条记录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)
如果您要检索所有数据,然后作为第二步写入文件,那么所有 db 数据都在内存中。如果您将数据流式传输到文件,则不会发生这种情况。即,而不是
data=...
while (rs.next()){
... add rs value to data
}
..write data to file
就像是
file=...
while (rs.next()){
write rs to file
}
设置 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();
}
获取缓冲区/释放行为取决于 JDBC 驱动程序以及 JVM 的垃圾收集器。在写入 FileOutputStream 之前你是否在做任何缓冲(这可能会阻止你的内存被垃圾收集)?
尝试使用-Xms
和-Xmx
java 运行时参数调整 Java 堆大小。例子:
java -Xms1024M -Xmx1024M com.mypkg.MyResultSetReader
上面的命令将为您的程序提供 1GB 的堆空间。如果这是一个临时工具,或者您不希望 ResultSet 大小增加,这可能是一个永久的解决方案。