» tagged pages
» logout

(Feed found, click Add Page to syndicate.) Error finding feed, please try again » Find feed title

A Blog Page allows you to add entries, for news or other time sensitive postings

(Login required to save to your tagged pages.)
(or Cancel)

Recent Edits

editing re-applied 61.95.184.98

Hibernate BAG vs IDBAG Performance Comparison

October 9, 2006
Hibernate BAG IDBAG Comparison

_Compare performance of bag and idbag mappings._(Created before October 1st, 2006) mappings._

» complete change

_Compare performance of bag and idbag mappings._(Created before October 1st, 2006) mappings._

[[Hibernate]] is well known for its ability to help developers to persist collections of dependent elements, but that comes at a price. What is the the cost?

Hibernate provides us with numerous mapping options, but let's focus on two: bag, and idbag. On the application code level the usage of bag and idbag tags is exactly the same. The differences are hidden in the Hibernate mapping files and in the database schema. Let's look at the DB schema:

h2. create-db.sql

<pre>

1

2 CREATE TABLE bag_main_objects (

3 id varchar(40) PRIMARY KEY,

4 name varchar(100)

5 );

6

7 CREATE TABLE idbag_dependent_objects (

8 id varchar(40) PRIMARY KEY,

9 main_id varchar(40),

10 val char(255)

11 );

12

13 CREATE TABLE bag_dependent_objects (

14 main_id varchar(40),

15 val char(255)

16 );

17

</pre>

Here we create do tables for dependent objects: table bag_dependent_object does not have a surrogate key, and table idbag_dependent_objects that has surrogate key. For simplicity we will just have values in the dependent objects table, but we as well could store keys to another table that will allow us to implements many-to-many relationships.

Then we will populate those tables with 100 main object and with 20 dependent objects per main object.

h2. DBSetterImpl.java

<pre>

27

28 public void generateTestData( Connection c ) throws SQLException{

29 for( int main_id = 0; main_id < MAIN_OBJ_ID_LIMIT; main_id++){

30 exec( c, "INSERT INTO bag_main_objects (id, name ) VALUES ( '"+ main_id +"','main-obj-"

+ main_id + "')");

31 for( int j = 0; j < DEPENDENT_OBJ_LIMIT; j++ ){

32 exec( c, "INSERT INTO idbag_dependent_objects(id, main_id, val) VALUES " +

33 "( 'm"+ main_id + "d"+ j +"','" + main_id + "','value of " +main_id + "d"+ j +"')");

34 exec( c, "INSERT INTO bag_dependent_objects(main_id, val) VALUES " +

35 "('" + main_id + "','value of " +main_id + "d"+ j

+"kjhdsafjhsjhdfkhgskjhdfkjhsgkdjfhgkjshdfgk asjfhdg akksddg aslkdkhfg alsidf')");

36 }

37 }

38 }

</pre>

BAG mapping is the example of un-optimized collection handling, it sure looks nice in the code: we simply add, update, or delete objects from the collection and Hibernate stores our changes. However for bag Hibernate uses a rather brutal force strategy: it deletes all the relevant rows from decent objects table and then inserts all the current collection content back into the database.

For example, lets assume that we have 20 dependent objects in a collection of dependent objects. If we delete just one object from the collection then Hibernate will execute 1 delete statement to delete all 20 rows, and then 19 insert statements to insert remaining 19 objects back into the database.

Here is how the mapping file looks:

h2. bag.hbm.xml

<code>

<pre>

5

6 <hibernate-mapping package="com.sourcelabs.hibernate.bhw.bags" >

7

8 <class table="bag_main_objects" name="BagContainerObj" lazy="false" >

9 <id name="id" >

10 <generator class="uuid"/>

11 </id>

12 <property name="name" />

13 <bag name="dependentObjects" table="bag_dependent_objects" lazy="false">

14 <key column="main_id" />

15 <element type="java.lang.String" column="val"/>

16 </bag>

17 </class>

18 </hibernate-mapping>

</pre>

</code>

IDBAG mapping is much smarter than BAG but requires ID column in the table of dependent objects. When we change collection content or update its members Hibernate will issue only necessary [[SQL]] update statements. If we delete one object from the collection, then Hibernate will execute only one SQL delete statement. IDBAG mapping looks as the following:

h2. idbag.hbm.xml

<code>

<pre>

<hibernate-mapping package="com.sourcelabs.hibernate.bhw.bags" >

6

7 <class table="bag_main_objects" name="BagContainerObj" lazy="false" >

8 <id name="id" >

9 <generator class="uuid"/>

10 </id>

11 <property name="name" />

12 <idbag name="dependentObjects" table="idbag_dependent_objects" lazy="false">

13 <collection-id column="id" type="java.lang.String">

14 <generator class="uuid"/>

15 </collection-id>

16 <key column="main_id" />

17 <element type="java.lang.String" column="val"/>

18 </idbag>

19 </class>

20 </hibernate-mapping>

</pre>

</code>

Both our mappings map collection of Strings to a list field for the same object, that is right, the same object have two different mappings, they of course cannot be used simultaneously in the same session, therefore we will run our tests sequentially:

h2. BagContainerObj.java

<pre>

public class BagContainerObj {

11 String id;

12 String name;

13 List dependentObjects;

14

15 public String getId(){

16 return id;

17 }

18

19 public void setId( String id ){

20 this.id = id;

21 }

22

23 public String getName(){

24 return name;

25 }

26

27 public void setName( String name ){

28 this.name = name;

29 }

30

31 public List getDependentObjects(){

32 return dependentObjects;

33 }

34

35 public void setDependentObjects( List dependentObjects ){

36 this.dependentObjects = dependentObjects;

37 }

38 }

39

</pre>

Running our tests produces the expected results: IDBAG collection is approximately 5 times faster than BAG mapping. And the advantage of IDBAG becomes even more noticeable with increase in the number of objects in the collection.

<pre>

run-class:

[java] [main] WARN net.sf.ehcache.config.Configurator

- No configuration found. Configuring ehcache

from ehcache -failsafe.xml found in the classpath: jar:file:

/home/kosta/.m2/repository/net/sf/ehcache/ehcache

/1.1-1/ehcache-1.1-1.jar!/ehcache-failsafe.xml

[java] USING BAG

[java] 613 [main] INFO org.springframework.aop.framework.DefaultAopProxyFactory

- CGLIB2 available: pro

xyTargetClass feature enabled

[java] 616 [main] INFO org.springframework.core.CollectionFactory

- JDK 1.4+ collections available

[java] 627 [main] INFO org.springframework.core.CollectionFactory

- Commons Collections 3.x available

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1716 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1372 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1178 ms

[java] Average::1422.3333333333333 ms

[java] USING IDBAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 485 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 438 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 526 ms

[java] Average::483.6666666666667 ms

[java] USING BAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1367 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1292 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1353 ms

[java] Average::1337.3333333333333 ms

[java] USING IDBAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 413 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 419 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 402 ms

[java] Average::411.6666666666667 ms

</pre>

The testing environment:

<pre>

kosta@swan ~/dev/hb-beyond-hw $ java -version

java version "1.5.0_06"

Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)

Java HotSpot(TM) Server VM (build 1.5.0_06-b05, mixed mode)

kosta@swan ~/dev/hb-beyond-hw $ uname -a

Linux swan 2.6.14-gentoo-r2 #1 SMP Wed Dec 21 09:41:13

PST 2005 x86_64 Intel(R) Xeon(TM) CPU 2.80GHz GenuineIntel GNU/Linux

</pre>

*BAGs brute force strategy is surely necessary for update and delete operations, but Hibernate could do a better job optimizing add (insert) operations. There is a little need for deleteing and reinserting all the members of the collection just to add one more record.*

editing undone by 61.95.184.98

Hibernate BAG vs IDBAG Performance Comparison

October 9, 2006
“sdffbh”
Hibernate BAG IDBAG Comparison

_Compare performance of bag and idbag mappings._ mappings._(Created before October 1st, 2006)

» complete change

_Compare performance of bag and idbag mappings._ mappings._(Created before October 1st, 2006)

[[Hibernate]] is well known for its ability to help developers to persist collections of dependent elements, but that comes at a price. What is the the cost?

Hibernate provides us with numerous mapping options, but let's focus on two: bag, and idbag. On the application code level the usage of bag and idbag tags is exactly the same. The differences are hidden in the Hibernate mapping files and in the database schema. Let's look at the DB schema:

h2. create-db.sql

<pre>

1

2 CREATE TABLE bag_main_objects (

3 id varchar(40) PRIMARY KEY,

4 name varchar(100)

5 );

6

7 CREATE TABLE idbag_dependent_objects (

8 id varchar(40) PRIMARY KEY,

9 main_id varchar(40),

10 val char(255)

11 );

12

13 CREATE TABLE bag_dependent_objects (

14 main_id varchar(40),

15 val char(255)

16 );

17

</pre>

Here we create do tables for dependent objects: table bag_dependent_object does not have a surrogate key, and table idbag_dependent_objects that has surrogate key. For simplicity we will just have values in the dependent objects table, but we as well could store keys to another table that will allow us to implements many-to-many relationships.

Then we will populate those tables with 100 main object and with 20 dependent objects per main object.

h2. DBSetterImpl.java

<pre>

27

28 public void generateTestData( Connection c ) throws SQLException{

29 for( int main_id = 0; main_id < MAIN_OBJ_ID_LIMIT; main_id++){

30 exec( c, "INSERT INTO bag_main_objects (id, name ) VALUES ( '"+ main_id +"','main-obj-"

+ main_id + "')");

31 for( int j = 0; j < DEPENDENT_OBJ_LIMIT; j++ ){

32 exec( c, "INSERT INTO idbag_dependent_objects(id, main_id, val) VALUES " +

33 "( 'm"+ main_id + "d"+ j +"','" + main_id + "','value of " +main_id + "d"+ j +"')");

34 exec( c, "INSERT INTO bag_dependent_objects(main_id, val) VALUES " +

35 "('" + main_id + "','value of " +main_id + "d"+ j

+"kjhdsafjhsjhdfkhgskjhdfkjhsgkdjfhgkjshdfgk asjfhdg akksddg aslkdkhfg alsidf')");

36 }

37 }

38 }

</pre>

BAG mapping is the example of un-optimized collection handling, it sure looks nice in the code: we simply add, update, or delete objects from the collection and Hibernate stores our changes. However for bag Hibernate uses a rather brutal force strategy: it deletes all the relevant rows from decent objects table and then inserts all the current collection content back into the database.

For example, lets assume that we have 20 dependent objects in a collection of dependent objects. If we delete just one object from the collection then Hibernate will execute 1 delete statement to delete all 20 rows, and then 19 insert statements to insert remaining 19 objects back into the database.

Here is how the mapping file looks:

h2. bag.hbm.xml

<code>

<pre>

5

6 <hibernate-mapping package="com.sourcelabs.hibernate.bhw.bags" >

7

8 <class table="bag_main_objects" name="BagContainerObj" lazy="false" >

9 <id name="id" >

10 <generator class="uuid"/>

11 </id>

12 <property name="name" />

13 <bag name="dependentObjects" table="bag_dependent_objects" lazy="false">

14 <key column="main_id" />

15 <element type="java.lang.String" column="val"/>

16 </bag>

17 </class>

18 </hibernate-mapping>

</pre>

</code>

IDBAG mapping is much smarter than BAG but requires ID column in the table of dependent objects. When we change collection content or update its members Hibernate will issue only necessary [[SQL]] update statements. If we delete one object from the collection, then Hibernate will execute only one SQL delete statement. IDBAG mapping looks as the following:

h2. idbag.hbm.xml

<code>

<pre>

<hibernate-mapping package="com.sourcelabs.hibernate.bhw.bags" >

6

7 <class table="bag_main_objects" name="BagContainerObj" lazy="false" >

8 <id name="id" >

9 <generator class="uuid"/>

10 </id>

11 <property name="name" />

12 <idbag name="dependentObjects" table="idbag_dependent_objects" lazy="false">

13 <collection-id column="id" type="java.lang.String">

14 <generator class="uuid"/>

15 </collection-id>

16 <key column="main_id" />

17 <element type="java.lang.String" column="val"/>

18 </idbag>

19 </class>

20 </hibernate-mapping>

</pre>

</code>

Both our mappings map collection of Strings to a list field for the same object, that is right, the same object have two different mappings, they of course cannot be used simultaneously in the same session, therefore we will run our tests sequentially:

h2. BagContainerObj.java

<pre>

public class BagContainerObj {

11 String id;

12 String name;

13 List dependentObjects;

14

15 public String getId(){

16 return id;

17 }

18

19 public void setId( String id ){

20 this.id = id;

21 }

22

23 public String getName(){

24 return name;

25 }

26

27 public void setName( String name ){

28 this.name = name;

29 }

30

31 public List getDependentObjects(){

32 return dependentObjects;

33 }

34

35 public void setDependentObjects( List dependentObjects ){

36 this.dependentObjects = dependentObjects;

37 }

38 }

39

</pre>

Running our tests produces the expected results: IDBAG collection is approximately 5 times faster than BAG mapping. And the advantage of IDBAG becomes even more noticeable with increase in the number of objects in the collection.

<pre>

run-class:

[java] [main] WARN net.sf.ehcache.config.Configurator

- No configuration found. Configuring ehcache

from ehcache -failsafe.xml found in the classpath: jar:file:

/home/kosta/.m2/repository/net/sf/ehcache/ehcache

/1.1-1/ehcache-1.1-1.jar!/ehcache-failsafe.xml

[java] USING BAG

[java] 613 [main] INFO org.springframework.aop.framework.DefaultAopProxyFactory

- CGLIB2 available: pro

xyTargetClass feature enabled

[java] 616 [main] INFO org.springframework.core.CollectionFactory

- JDK 1.4+ collections available

[java] 627 [main] INFO org.springframework.core.CollectionFactory

- Commons Collections 3.x available

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1716 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1372 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1178 ms

[java] Average::1422.3333333333333 ms

[java] USING IDBAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 485 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 438 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 526 ms

[java] Average::483.6666666666667 ms

[java] USING BAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1367 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1292 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1353 ms

[java] Average::1337.3333333333333 ms

[java] USING IDBAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 413 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 419 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 402 ms

[java] Average::411.6666666666667 ms

</pre>

The testing environment:

<pre>

kosta@swan ~/dev/hb-beyond-hw $ java -version

java version "1.5.0_06"

Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)

Java HotSpot(TM) Server VM (build 1.5.0_06-b05, mixed mode)

kosta@swan ~/dev/hb-beyond-hw $ uname -a

Linux swan 2.6.14-gentoo-r2 #1 SMP Wed Dec 21 09:41:13

PST 2005 x86_64 Intel(R) Xeon(TM) CPU 2.80GHz GenuineIntel GNU/Linux

</pre>

*BAGs brute force strategy is surely necessary for update and delete operations, but Hibernate could do a better job optimizing add (insert) operations. There is a little need for deleteing and reinserting all the members of the collection just to add one more record.*

editing undone by 61.95.184.98

Hibernate BAG vs IDBAG Performance Comparison

October 9, 2006
Hibernate BAG IDBAG Comparison

_Compare performance of bag and idbag mappings._ mappings._(Created before October 1st, 2006)

» complete change

_Compare performance of bag and idbag mappings._ mappings._(Created before October 1st, 2006)

[[Hibernate]] is well known for its ability to help developers to persist collections of dependent elements, but that comes at a price. What is the the cost?

Hibernate provides us with numerous mapping options, but let's focus on two: bag, and idbag. On the application code level the usage of bag and idbag tags is exactly the same. The differences are hidden in the Hibernate mapping files and in the database schema. Let's look at the DB schema:

h2. create-db.sql

<pre>

1

2 CREATE TABLE bag_main_objects (

3 id varchar(40) PRIMARY KEY,

4 name varchar(100)

5 );

6

7 CREATE TABLE idbag_dependent_objects (

8 id varchar(40) PRIMARY KEY,

9 main_id varchar(40),

10 val char(255)

11 );

12

13 CREATE TABLE bag_dependent_objects (

14 main_id varchar(40),

15 val char(255)

16 );

17

</pre>

Here we create do tables for dependent objects: table bag_dependent_object does not have a surrogate key, and table idbag_dependent_objects that has surrogate key. For simplicity we will just have values in the dependent objects table, but we as well could store keys to another table that will allow us to implements many-to-many relationships.

Then we will populate those tables with 100 main object and with 20 dependent objects per main object.

h2. DBSetterImpl.java

<pre>

27

28 public void generateTestData( Connection c ) throws SQLException{

29 for( int main_id = 0; main_id < MAIN_OBJ_ID_LIMIT; main_id++){

30 exec( c, "INSERT INTO bag_main_objects (id, name ) VALUES ( '"+ main_id +"','main-obj-"

+ main_id + "')");

31 for( int j = 0; j < DEPENDENT_OBJ_LIMIT; j++ ){

32 exec( c, "INSERT INTO idbag_dependent_objects(id, main_id, val) VALUES " +

33 "( 'm"+ main_id + "d"+ j +"','" + main_id + "','value of " +main_id + "d"+ j +"')");

34 exec( c, "INSERT INTO bag_dependent_objects(main_id, val) VALUES " +

35 "('" + main_id + "','value of " +main_id + "d"+ j

+"kjhdsafjhsjhdfkhgskjhdfkjhsgkdjfhgkjshdfgk asjfhdg akksddg aslkdkhfg alsidf')");

36 }

37 }

38 }

</pre>

BAG mapping is the example of un-optimized collection handling, it sure looks nice in the code: we simply add, update, or delete objects from the collection and Hibernate stores our changes. However for bag Hibernate uses a rather brutal force strategy: it deletes all the relevant rows from decent objects table and then inserts all the current collection content back into the database.

For example, lets assume that we have 20 dependent objects in a collection of dependent objects. If we delete just one object from the collection then Hibernate will execute 1 delete statement to delete all 20 rows, and then 19 insert statements to insert remaining 19 objects back into the database.

Here is how the mapping file looks:

h2. bag.hbm.xml

<code>

<pre>

5

6 <hibernate-mapping package="com.sourcelabs.hibernate.bhw.bags" >

7

8 <class table="bag_main_objects" name="BagContainerObj" lazy="false" >

9 <id name="id" >

10 <generator class="uuid"/>

11 </id>

12 <property name="name" />

13 <bag name="dependentObjects" table="bag_dependent_objects" lazy="false">

14 <key column="main_id" />

15 <element type="java.lang.String" column="val"/>

16 </bag>

17 </class>

18 </hibernate-mapping>

</pre>

</code>

IDBAG mapping is much smarter than BAG but requires ID column in the table of dependent objects. When we change collection content or update its members Hibernate will issue only necessary [[SQL]] update statements. If we delete one object from the collection, then Hibernate will execute only one SQL delete statement. IDBAG mapping looks as the following:

h2. idbag.hbm.xml

<code>

<pre>

<hibernate-mapping package="com.sourcelabs.hibernate.bhw.bags" >

6

7 <class table="bag_main_objects" name="BagContainerObj" lazy="false" >

8 <id name="id" >

9 <generator class="uuid"/>

10 </id>

11 <property name="name" />

12 <idbag name="dependentObjects" table="idbag_dependent_objects" lazy="false">

13 <collection-id column="id" type="java.lang.String">

14 <generator class="uuid"/>

15 </collection-id>

16 <key column="main_id" />

17 <element type="java.lang.String" column="val"/>

18 </idbag>

19 </class>

20 </hibernate-mapping>

</pre>

</code>

Both our mappings map collection of Strings to a list field for the same object, that is right, the same object have two different mappings, they of course cannot be used simultaneously in the same session, therefore we will run our tests sequentially:

h2. BagContainerObj.java

<pre>

public class BagContainerObj {

11 String id;

12 String name;

13 List dependentObjects;

14

15 public String getId(){

16 return id;

17 }

18

19 public void setId( String id ){

20 this.id = id;

21 }

22

23 public String getName(){

24 return name;

25 }

26

27 public void setName( String name ){

28 this.name = name;

29 }

30

31 public List getDependentObjects(){

32 return dependentObjects;

33 }

34

35 public void setDependentObjects( List dependentObjects ){

36 this.dependentObjects = dependentObjects;

37 }

38 }

39

</pre>

Running our tests produces the expected results: IDBAG collection is approximately 5 times faster than BAG mapping. And the advantage of IDBAG becomes even more noticeable with increase in the number of objects in the collection.

<pre>

run-class:

[java] [main] WARN net.sf.ehcache.config.Configurator

- No configuration found. Configuring ehcache

from ehcache -failsafe.xml found in the classpath: jar:file:

/home/kosta/.m2/repository/net/sf/ehcache/ehcache

/1.1-1/ehcache-1.1-1.jar!/ehcache-failsafe.xml

[java] USING BAG

[java] 613 [main] INFO org.springframework.aop.framework.DefaultAopProxyFactory

- CGLIB2 available: pro

xyTargetClass feature enabled

[java] 616 [main] INFO org.springframework.core.CollectionFactory

- JDK 1.4+ collections available

[java] 627 [main] INFO org.springframework.core.CollectionFactory

- Commons Collections 3.x available

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1716 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1372 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1178 ms

[java] Average::1422.3333333333333 ms

[java] USING IDBAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 485 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 438 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 526 ms

[java] Average::483.6666666666667 ms

[java] USING BAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1367 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1292 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1353 ms

[java] Average::1337.3333333333333 ms

[java] USING IDBAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 413 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 419 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 402 ms

[java] Average::411.6666666666667 ms

</pre>

The testing environment:

<pre>

kosta@swan ~/dev/hb-beyond-hw $ java -version

java version "1.5.0_06"

Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)

Java HotSpot(TM) Server VM (build 1.5.0_06-b05, mixed mode)

kosta@swan ~/dev/hb-beyond-hw $ uname -a

Linux swan 2.6.14-gentoo-r2 #1 SMP Wed Dec 21 09:41:13

PST 2005 x86_64 Intel(R) Xeon(TM) CPU 2.80GHz GenuineIntel GNU/Linux

</pre>

*BAGs brute force strategy is surely necessary for update and delete operations, but Hibernate could do a better job optimizing add (insert) operations. There is a little need for deleteing and reinserting all the members of the collection just to add one more record.*

Undo this change because:
edit by 61.49.138.183

Hibernate BAG vs IDBAG Performance Comparison

October 5, 2006
“Added a date, essential when doing technology related searches”
Hibernate BAG IDBAG Comparison

_Compare performance of bag and idbag mappings._(Created before October 1st, 2006) mappings._

» complete change

_Compare performance of bag and idbag mappings._(Created before October 1st, 2006) mappings._

[[Hibernate]] is well known for its ability to help developers to persist collections of dependent elements, but that comes at a price. What is the the cost?

Hibernate provides us with numerous mapping options, but let's focus on two: bag, and idbag. On the application code level the usage of bag and idbag tags is exactly the same. The differences are hidden in the Hibernate mapping files and in the database schema. Let's look at the DB schema:

h2. create-db.sql

<pre>

1

2 CREATE TABLE bag_main_objects (

3 id varchar(40) PRIMARY KEY,

4 name varchar(100)

5 );

6

7 CREATE TABLE idbag_dependent_objects (

8 id varchar(40) PRIMARY KEY,

9 main_id varchar(40),

10 val char(255)

11 );

12

13 CREATE TABLE bag_dependent_objects (

14 main_id varchar(40),

15 val char(255)

16 );

17

</pre>

Here we create do tables for dependent objects: table bag_dependent_object does not have a surrogate key, and table idbag_dependent_objects that has surrogate key. For simplicity we will just have values in the dependent objects table, but we as well could store keys to another table that will allow us to implements many-to-many relationships.

Then we will populate those tables with 100 main object and with 20 dependent objects per main object.

h2. DBSetterImpl.java

<pre>

27

28 public void generateTestData( Connection c ) throws SQLException{

29 for( int main_id = 0; main_id < MAIN_OBJ_ID_LIMIT; main_id++){

30 exec( c, "INSERT INTO bag_main_objects (id, name ) VALUES ( '"+ main_id +"','main-obj-"

+ main_id + "')");

31 for( int j = 0; j < DEPENDENT_OBJ_LIMIT; j++ ){

32 exec( c, "INSERT INTO idbag_dependent_objects(id, main_id, val) VALUES " +

33 "( 'm"+ main_id + "d"+ j +"','" + main_id + "','value of " +main_id + "d"+ j +"')");

34 exec( c, "INSERT INTO bag_dependent_objects(main_id, val) VALUES " +

35 "('" + main_id + "','value of " +main_id + "d"+ j

+"kjhdsafjhsjhdfkhgskjhdfkjhsgkdjfhgkjshdfgk asjfhdg akksddg aslkdkhfg alsidf')");

36 }

37 }

38 }

</pre>

BAG mapping is the example of un-optimized collection handling, it sure looks nice in the code: we simply add, update, or delete objects from the collection and Hibernate stores our changes. However for bag Hibernate uses a rather brutal force strategy: it deletes all the relevant rows from decent objects table and then inserts all the current collection content back into the database.

For example, lets assume that we have 20 dependent objects in a collection of dependent objects. If we delete just one object from the collection then Hibernate will execute 1 delete statement to delete all 20 rows, and then 19 insert statements to insert remaining 19 objects back into the database.

Here is how the mapping file looks:

h2. bag.hbm.xml

<code>

<pre>

5

6 <hibernate-mapping package="com.sourcelabs.hibernate.bhw.bags" >

7

8 <class table="bag_main_objects" name="BagContainerObj" lazy="false" >

9 <id name="id" >

10 <generator class="uuid"/>

11 </id>

12 <property name="name" />

13 <bag name="dependentObjects" table="bag_dependent_objects" lazy="false">

14 <key column="main_id" />

15 <element type="java.lang.String" column="val"/>

16 </bag>

17 </class>

18 </hibernate-mapping>

</pre>

</code>

IDBAG mapping is much smarter than BAG but requires ID column in the table of dependent objects. When we change collection content or update its members Hibernate will issue only necessary [[SQL]] update statements. If we delete one object from the collection, then Hibernate will execute only one SQL delete statement. IDBAG mapping looks as the following:

h2. idbag.hbm.xml

<code>

<pre>

<hibernate-mapping package="com.sourcelabs.hibernate.bhw.bags" >

6

7 <class table="bag_main_objects" name="BagContainerObj" lazy="false" >

8 <id name="id" >

9 <generator class="uuid"/>

10 </id>

11 <property name="name" />

12 <idbag name="dependentObjects" table="idbag_dependent_objects" lazy="false">

13 <collection-id column="id" type="java.lang.String">

14 <generator class="uuid"/>

15 </collection-id>

16 <key column="main_id" />

17 <element type="java.lang.String" column="val"/>

18 </idbag>

19 </class>

20 </hibernate-mapping>

</pre>

</code>

Both our mappings map collection of Strings to a list field for the same object, that is right, the same object have two different mappings, they of course cannot be used simultaneously in the same session, therefore we will run our tests sequentially:

h2. BagContainerObj.java

<pre>

public class BagContainerObj {

11 String id;

12 String name;

13 List dependentObjects;

14

15 public String getId(){

16 return id;

17 }

18

19 public void setId( String id ){

20 this.id = id;

21 }

22

23 public String getName(){

24 return name;

25 }

26

27 public void setName( String name ){

28 this.name = name;

29 }

30

31 public List getDependentObjects(){

32 return dependentObjects;

33 }

34

35 public void setDependentObjects( List dependentObjects ){

36 this.dependentObjects = dependentObjects;

37 }

38 }

39

</pre>

Running our tests produces the expected results: IDBAG collection is approximately 5 times faster than BAG mapping. And the advantage of IDBAG becomes even more noticeable with increase in the number of objects in the collection.

<pre>

run-class:

[java] [main] WARN net.sf.ehcache.config.Configurator

- No configuration found. Configuring ehcache

from ehcache -failsafe.xml found in the classpath: jar:file:

/home/kosta/.m2/repository/net/sf/ehcache/ehcache

/1.1-1/ehcache-1.1-1.jar!/ehcache-failsafe.xml

[java] USING BAG

[java] 613 [main] INFO org.springframework.aop.framework.DefaultAopProxyFactory

- CGLIB2 available: pro

xyTargetClass feature enabled

[java] 616 [main] INFO org.springframework.core.CollectionFactory

- JDK 1.4+ collections available

[java] 627 [main] INFO org.springframework.core.CollectionFactory

- Commons Collections 3.x available

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1716 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1372 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1178 ms

[java] Average::1422.3333333333333 ms

[java] USING IDBAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 485 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 438 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 526 ms

[java] Average::483.6666666666667 ms

[java] USING BAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1367 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1292 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1353 ms

[java] Average::1337.3333333333333 ms

[java] USING IDBAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 413 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 419 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 402 ms

[java] Average::411.6666666666667 ms

</pre>

The testing environment:

<pre>

kosta@swan ~/dev/hb-beyond-hw $ java -version

java version "1.5.0_06"

Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)

Java HotSpot(TM) Server VM (build 1.5.0_06-b05, mixed mode)

kosta@swan ~/dev/hb-beyond-hw $ uname -a

Linux swan 2.6.14-gentoo-r2 #1 SMP Wed Dec 21 09:41:13

PST 2005 x86_64 Intel(R) Xeon(TM) CPU 2.80GHz GenuineIntel GNU/Linux

</pre>

*BAGs brute force strategy is surely necessary for update and delete operations, but Hibernate could do a better job optimizing add (insert) operations. There is a little need for deleteing and reinserting all the members of the collection just to add one more record.*

created by alex

Hibernate BAG vs IDBAG Performance Comparison

June 7, 2006
The page was created.
Hibernate BAG IDBAG Comparison
Hibernate BAG vs IDBAG Performance Comparison
Article

_Compare performance of bag and idbag mappings._

[[Hibernate]] is well known for its ability to help developers to persist...

» complete change

_Compare performance of bag and idbag mappings._

[[Hibernate]] is well known for its ability to help developers to persist collections of dependent elements, but that comes at a price. What is the the cost?

Hibernate provides us with numerous mapping options, but let's focus on two: bag, and idbag. On the application code level the usage of bag and idbag tags is exactly the same. The differences are hidden in the Hibernate mapping files and in the database schema. Let's look at the DB schema:

h2. create-db.sql

<pre>

1

2 CREATE TABLE bag_main_objects (

3 id varchar(40) PRIMARY KEY,

4 name varchar(100)

5 );

6

7 CREATE TABLE idbag_dependent_objects (

8 id varchar(40) PRIMARY KEY,

9 main_id varchar(40),

10 val char(255)

11 );

12

13 CREATE TABLE bag_dependent_objects (

14 main_id varchar(40),

15 val char(255)

16 );

17

</pre>

Here we create do tables for dependent objects: table bag_dependent_object does not have a surrogate key, and table idbag_dependent_objects that has surrogate key. For simplicity we will just have values in the dependent objects table, but we as well could store keys to another table that will allow us to implements many-to-many relationships.

Then we will populate those tables with 100 main object and with 20 dependent objects per main object.

h2. DBSetterImpl.java

<pre>

27

28 public void generateTestData( Connection c ) throws SQLException{

29 for( int main_id = 0; main_id < MAIN_OBJ_ID_LIMIT; main_id++){

30 exec( c, "INSERT INTO bag_main_objects (id, name ) VALUES ( '"+ main_id +"','main-obj-"

+ main_id + "')");

31 for( int j = 0; j < DEPENDENT_OBJ_LIMIT; j++ ){

32 exec( c, "INSERT INTO idbag_dependent_objects(id, main_id, val) VALUES " +

33 "( 'm"+ main_id + "d"+ j +"','" + main_id + "','value of " +main_id + "d"+ j +"')");

34 exec( c, "INSERT INTO bag_dependent_objects(main_id, val) VALUES " +

35 "('" + main_id + "','value of " +main_id + "d"+ j

+"kjhdsafjhsjhdfkhgskjhdfkjhsgkdjfhgkjshdfgk asjfhdg akksddg aslkdkhfg alsidf')");

36 }

37 }

38 }

</pre>

BAG mapping is the example of un-optimized collection handling, it sure looks nice in the code: we simply add, update, or delete objects from the collection and Hibernate stores our changes. However for bag Hibernate uses a rather brutal force strategy: it deletes all the relevant rows from decent objects table and then inserts all the current collection content back into the database.

For example, lets assume that we have 20 dependent objects in a collection of dependent objects. If we delete just one object from the collection then Hibernate will execute 1 delete statement to delete all 20 rows, and then 19 insert statements to insert remaining 19 objects back into the database.

Here is how the mapping file looks:

h2. bag.hbm.xml

<code>

<pre>

5

6 <hibernate-mapping package="com.sourcelabs.hibernate.bhw.bags" >

7

8 <class table="bag_main_objects" name="BagContainerObj" lazy="false" >

9 <id name="id" >

10 <generator class="uuid"/>

11 </id>

12 <property name="name" />

13 <bag name="dependentObjects" table="bag_dependent_objects" lazy="false">

14 <key column="main_id" />

15 <element type="java.lang.String" column="val"/>

16 </bag>

17 </class>

18 </hibernate-mapping>

</pre>

</code>

IDBAG mapping is much smarter than BAG but requires ID column in the table of dependent objects. When we change collection content or update its members Hibernate will issue only necessary [[SQL]] update statements. If we delete one object from the collection, then Hibernate will execute only one SQL delete statement. IDBAG mapping looks as the following:

h2. idbag.hbm.xml

<code>

<pre>

<hibernate-mapping package="com.sourcelabs.hibernate.bhw.bags" >

6

7 <class table="bag_main_objects" name="BagContainerObj" lazy="false" >

8 <id name="id" >

9 <generator class="uuid"/>

10 </id>

11 <property name="name" />

12 <idbag name="dependentObjects" table="idbag_dependent_objects" lazy="false">

13 <collection-id column="id" type="java.lang.String">

14 <generator class="uuid"/>

15 </collection-id>

16 <key column="main_id" />

17 <element type="java.lang.String" column="val"/>

18 </idbag>

19 </class>

20 </hibernate-mapping>

</pre>

</code>

Both our mappings map collection of Strings to a list field for the same object, that is right, the same object have two different mappings, they of course cannot be used simultaneously in the same session, therefore we will run our tests sequentially:

h2. BagContainerObj.java

<pre>

public class BagContainerObj {

11 String id;

12 String name;

13 List dependentObjects;

14

15 public String getId(){

16 return id;

17 }

18

19 public void setId( String id ){

20 this.id = id;

21 }

22

23 public String getName(){

24 return name;

25 }

26

27 public void setName( String name ){

28 this.name = name;

29 }

30

31 public List getDependentObjects(){

32 return dependentObjects;

33 }

34

35 public void setDependentObjects( List dependentObjects ){

36 this.dependentObjects = dependentObjects;

37 }

38 }

39

</pre>

Running our tests produces the expected results: IDBAG collection is approximately 5 times faster than BAG mapping. And the advantage of IDBAG becomes even more noticeable with increase in the number of objects in the collection.

<pre>

run-class:

[java] [main] WARN net.sf.ehcache.config.Configurator

- No configuration found. Configuring ehcache

from ehcache -failsafe.xml found in the classpath: jar:file:

/home/kosta/.m2/repository/net/sf/ehcache/ehcache

/1.1-1/ehcache-1.1-1.jar!/ehcache-failsafe.xml

[java] USING BAG

[java] 613 [main] INFO org.springframework.aop.framework.DefaultAopProxyFactory

- CGLIB2 available: pro

xyTargetClass feature enabled

[java] 616 [main] INFO org.springframework.core.CollectionFactory

- JDK 1.4+ collections available

[java] 627 [main] INFO org.springframework.core.CollectionFactory

- Commons Collections 3.x available

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1716 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1372 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execAddElement 1178 ms

[java] Average::1422.3333333333333 ms

[java] USING IDBAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 485 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 438 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execAddElement 526 ms

[java] Average::483.6666666666667 ms

[java] USING BAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1367 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1292 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1d95da8

[java] execRemoveElement 1353 ms

[java] Average::1337.3333333333333 ms

[java] USING IDBAG

[java] Pass #1

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 413 ms

[java] Pass #2

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 419 ms

[java] Pass #3

[java] hibernateSessionFactory = org.hibernate.impl.SessionFactoryImpl@1a3b359

[java] execRemoveElement 402 ms

[java] Average::411.6666666666667 ms

</pre>

The testing environment:

<pre>

kosta@swan ~/dev/hb-beyond-hw $ java -version

java version "1.5.0_06"

Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)

Java HotSpot(TM) Server VM (build 1.5.0_06-b05, mixed mode)

kosta@swan ~/dev/hb-beyond-hw $ uname -a

Linux swan 2.6.14-gentoo-r2 #1 SMP Wed Dec 21 09:41:13

PST 2005 x86_64 Intel(R) Xeon(TM) CPU 2.80GHz GenuineIntel GNU/Linux

</pre>

*BAGs brute force strategy is surely necessary for update and delete operations, but Hibernate could do a better job optimizing add (insert) operations. There is a little need for deleteing and reinserting all the members of the collection just to add one more record.*

Undo this change because:
Username:
Password:
(or Cancel)