如何使用JDBC在文本文件中编写大量数据,而不会耗尽内存

时间:2009-08-25 10:28:26

标签: java jdbc recordset

我正在尝试使用JDBC从数据库创建转储文件。该文件应该是大约300 MB的大小,包含十列中的1.2到1.5百万条记录,但我的内存耗尽大约25万。

我的问题是java将整个记录集存储在内存中吗?我已经将记录集设置为只能向前读取,希望已经转储的记录将从内存中清除,但似乎并非如此。

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:7)

您应该在setFetchSize对象上使用Statement。以下示例一次仅从ResultSet

获取1000条记录
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();
}