Hibernate version: 3.1 rc 2
DB2 7.2.9
We are using the stateless session to read large amounts of data.
We have two table A and B with lots of rows (e.g.200000) and many columns.
Both tables and mappings are flat, i.e. no collection etc.
The table are read with two queries queryA and queryB.
The performance and memory consumption
of the queries differ in suprising ways depending
on some circumstances.
Here are some performance results for different szenarios:
1. StatelessSession
using queryA.list(), 20 sec
using queryB.list(), 33 sec
Memory Usage 350 MB
2. StatelessSession
using queryA.list(), 21 sec
using queryB.scroll() 1600 sec
Memory Usage 180 MB
3. StatelessSession
using queryA.list(), 21 sec
session.close and reopen
using queryB.scroll() 65 sec
Memory Usage 180 MB
4. StatelessSession
no queryA
using queryB.scroll() 65 sec
Memory Usage 25 MB
5. StatelessSession
using queryA.scroll() 21
using queryB.scroll() 63
Memory Usage 55 MB
6. (Stateful) Session
using queryA.list(), 20 sec
using queryB.scroll() 79 sec
Memory Usage 450 MB
Some remarks:
The problem is that queryB is 10 time slower in scenario 2.
The performance of the two queries should be independent of each other
in szenarios 1 and 2.
The memory consumption of stateless session is too large,
when using query.list().
The problem grows with the number of rows of table A.
There seems to be some kind of loop over all previous loaded
instance of A, when loading B via scroll.
SQL output consist only of the two queries.
Profiling with YourKit didnt reveal anything.
Any help would be appreciated.
Here are the files:
Code:
private static void queriesCursor(SessionFactory factory) {
StatelessSession session = factory.openStatelessSession();
Transaction tx = session.beginTransaction();
long t0 = System.currentTimeMillis();
Query queryA = session.createQuery("from A");
List listA = queryA.list();
System.out.println("query A: " + (System.currentTimeMillis()-t0) + " cnt: " + listA.size());
t0 = System.currentTimeMillis();
Query queryB = session.createQuery("from B");
ScrollableResults scroll = queryB.scroll();
int cnt=0;
while (scroll.next()) {
B b = (B) scroll.get(0);
b.getId();
cnt++;
}
System.out.println("query B: " + (System.currentTimeMillis()-t0) + " cnt: " + cnt);
tx.commit();
}
hibernate.cfg.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--<property name="hibernate.hbm2ddl.auto">update</property> -->
<property name="dialect">org.hibernate.dialect.DB2Dialect</property>
<property name="hibernate.default_schema">hib</property>
<property name="connection.driver_class">COM.ibm.db2.jdbc.app.DB2Driver</property>
<property name="connection.username">ifb</property>
<property name="connection.password">kennwort</property>
<property name="connection.url">jdbc:db2:dbtest</property>
<property name="jdbc.batch_size">20</property>
<!--<property name="hibernate.default_batch_fetch_size">20</property>-->
<property name="show_sql">true</property>
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.connection.release_mode">on_close</property>
<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<property name="c3p0.acquire_increment">1</property>
<property name="c3p0.idle_test_period">100</property>
<property name="c3p0.max_size">100</property>
<property name="c3p0.max_statements">100</property>
<property name="c3p0.min_size">1</property>
<property name="c3p0.timeout">100</property>
<!-- Mapping files -->
<mapping resource="test/A.hbm.xml"/>
<mapping resource="test/B.hbm.xml"/>
</session-factory>
</hibernate-configuration>
The classes A, B and corresponding table contain just simple doubles, int, Date etc.