views:

457

answers:

7

I need to access (read in) data repeatedly from a database in my java codes, and therefore adopted JDBC. However, it seems to me that using JDBC takes up a lot of memory. I tried to be careful about closing the objects created for JDBC (ResultSet, Statemenet), but still it seems to hog a lot of memeory especially compared to reading in input from a textfile. Does anybody know the best way to reduce memeory consumption? Thanks.

+3  A: 

It is very unlikely that 'JDBC' is a memory hog. JDBC is just a pipe. The amount of memory used will depend on what database you are talking to and, more importantly, what sort of queries you are running, and whether you are using cursors correctly.

You might look at Hibernate for help in managing memory usage when working with large amounts of data.

bmargulies
Can you explain how hibernate would use less memory than raw JDBC? Level 2 cache?
Sam Barnum
@Sam Barnum: See the section Fetching Strategies on this page: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html
R. Bemrose
+2  A: 

JDBC does not eat up very much memory for itself. It caches several pieces of metadata, but the vast majority of memory is taken up by the query results usually. The idea of it is just providing a standard interface of accessing your data, it is not very much of an implementation in its own right. That's why you need JDBC drivers that implement the specifics for each database product.

JDBC being not resource intensive is supported by the fact that you can run JDBC even on mobile devices with JavaME - a very resource limited environment.

So while you might appreciate the easier handling of data with frameworks like Hibernate or JPA, you should not worry about JDBC consuming any amount of resources worth mentioning in the context of the overall application.

As they say: Don't try to optimize things that are not a problem :)

Daniel Schneller
+2  A: 

If you ever encounter this problem then it's probably your own code which is a memory hog. This can happen if you haul the complete database contents into Java's memory. That's actually not JDBC's fault.

To reduce memory consumption, best is to fire as specific as possible SQL queries. Just only query the data you actually need, nothing else.

If you really need all the data of a table, then you're probably using the wrong tool with JDBC. Decent DB servers ships with more decent import/export tools for that. Give it a look first.

BalusC
+1  A: 

Its more a factor of the data you are loading than the JDBC library. Since JDBC calls involve a lot of data, I'd check that you don't have a lot of objects sitting around in a collection that isn't being released and making it to the generation 2 of the heap.

Kelly French
A: 

One time JDBC can use a lot of memory is if you're doing queries which return many rows from the database, and scrolling result sets are not supported by your JDBC driver. This causes all rows to be retrieved from the server, and potentially loaded into RAM.

The solution is to split your queries into smaller batches, or enable scrolling result sets if possible.

Sam Barnum
+1  A: 

JDBC is not a memory hog. The data it returns can be a huge memory hog.

One common problem with JDBC is that the result sets, which contain the huge amount of data (and are not always memory optimized), are not handled or closed correctly. In order to prevent memory leaks from ResultSet object lying around, the developer must take careful steps to make sure the memory is released before moving on. (Java handling most memory clean-up means this is a blind spot for most developers, so it isn't surprising.)

Consider using this code. It uses the "try/catch try/finally" pattern to definitively close the result set:

try{
    Statement stmt = conn.createStatement();
    try {
        ResultSet rs = stmt.createQuery("some sql");
        try {
            // ResultSet processing goes here
        } finally {
            rs.close();
        }
    } finally {
        stmt.close();
    }
}
catch ( SQLException ex ) { // exception processing for any problems. }

This guarantees that the result set is closed - even if a exception is thrown.

Jonathan B
Good text but bad code. That's now how it's to be done.
BalusC
don't forget the conn.close() in it's own finally block!
james
@BalusC - I can see why you might say that. A vanilla design has the finally{} at the end, after the catch. This design solves a few problems: not checking for nulls and avoiding the "missed close()" trap for a second exception. First, all of the close methods ALSO throw SQLException, this centralizes the catch block for them. The "missed close()" is tricker - if you use a single finally that also has a try/catch in it, and that method has more than one close(), any exception skips some of the close() statements.This may not be perfect code, so better ideas are always welcome!
Jonathan B
+2  A: 

I have to agree what others have said here, that JDBC itself doesn't use a large memory footprint. However if you're concerned about a particular JDBC operation using a lot of memory you could use either JConsole or a profiler to see how much heap is used during said method execution.

Jason Gritman