views:

29

answers:

2

Hi all, Currently I am using statement.executeQuery(qStr) in java to select a large amount of data from mysql. Unfortunatly, java keeps running out of memory at the statement.executeQuery(qStr) statement with exception java.lang.OutOfMemoryError: Java heap space. I am wondering if there is a method to stream load data from mysql. So that I can handle the selected data trunk by trunk to avoid running out of memory?

Note that: I am using eclipse and this post shows me how to increase the heap memory for java to use inside eclipse. But after I followed it's method, i am still running into the same problem.

Thanks in advance.

+1  A: 

Yes, you can set the FetchSize on a Statement to Integer.MIN_VALUE , the ResultSet should be TYPE_FORWARD_ONLY as well, though I believe that's the default.. MySQL treats that specially and enables streaming of the ResultSet instead of reading it all into memory, it's documented here

PreparedStatement stmt =  
 conn.prepareStatement(sql,ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
nos
Thanks guys for your answers. I tried it but comes out with another exception: "com.mysql.jdbc.RowDataDynamic$OperationNotSupportedException: Operation not supported for streaming result set". I am using the mysql-connector-java-5.1.13-bin.jar.Also, if I replaced Integer.MIN_VALUE with a specific number 100. Then the out of heap memory exception still appears.Any idea? Thanks.
Kenneth
Integer.MIN_VALUE is special within the mysql, setting it to anything else gives the default behavior. I don't know where you get that exception - so post the code where it happens.
nos
Thanks nos, I was trying to extract the relavent code to past here, then I found the problem source. it's the problem of calling the resultSet.getRow()...... Ok.. that's for help me.. I appreciate for your help. Thanks.
Kenneth
+1  A: 

By default, ResultSets are completely retrieved and stored in memory. If you are dealing with huge result sets, your heap will quickly be exhausted. You can change this behavior by creating the Statement instance like this:

 stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
          java.sql.ResultSet.CONCUR_READ_ONLY);
 stmt.setFetchSize(Integer.MIN_VALUE);

This creates a

forward-only, read-only result set, with a fetch size of Integer.MIN_VALUE serves as a signal to the driver to stream result sets row-by-row. After this any result sets created with the statement will be retrieved row-by-row.

See the MySQL documentation for more details and the caveats: http://dev.mysql.com/doc/refman/5.5/en/connector-j-reference-implementation-notes.html

bunting
Thanks guys for your answers. I tried it but comes out with another exception: "com.mysql.jdbc.RowDataDynamic$OperationNotSupportedException: Operation not supported for streaming result set". I am using the mysql-connector-java-5.1.13-bin.jar.Also, if I replaced Integer.MIN_VALUE with a specific number 100. Then the out of heap memory exception still appears.Any idea? Thanks.
Kenneth
For MySQL you must set the fetch size to Integer.MIN_VALUE, otherwise the driver reverts to the usual caching strategy of ResultSets.
bunting
The OperationNotSupportedException can have a number of reasons. To begin with, which MySQL version are you using (there's a known bug with version 5.1.6) ?
bunting
Thanks bunting, my mysql server is in version 5.1.43. And as I mentioned above, my mysql-connector is 5.1.13. Thanks.
Kenneth
Thank bunting, I found out the problem in my code now. It's because I still used resultSet.getRow() and it cause the exception threw... Thanks.
Kenneth