[b]Hibernate version:version 2.1.6, 9.8.2004 [/b]
You can find at
http://www.hibernate.org/15.html, Performance Q&A, the statement: "Generally the overhead is much less than 10% of the JDBC calls". In my performance test app the overhead is between 100% and 2300%. What's wrong with it?
The test inserts/reads 10,000 objects into/from a table with 53 columns. The database engine is a MS SQL Server and I use MS JDBC driver (- yes I should not, but I don't think it's better with another one).
I run the test with different transaction lengths. Here is what I measured:
1. Insert
1.1. HIBERNATE: objects per trans / seconds
100 / 51s
10 / 106s
1 / 703s
1.2. JDBC
100 / 23s
10 / 26s
1 / 30s
2. Read
2.1. HIBERNATE: seconds
46s
2.2. JDBC
22s
Who can explain this result?
Why are Hibernate transactions so much slower than JDBC transactions (I do not use any hibernate.transaction.factory_class)?
I'm sorry that I cannot provide the complete source code of my test project for you. My manager does not allow me to do since it contains too much product specific information.
I use one table with 53 columns. 8 columns are of type varchar, 45 columns are of type int.
The class mapped to the table has a "composite-id": two of the integer columns build a unique row ID. Thus, I have to derive the class from "Serializable" and have to implement "equals" and "hashCode" for it.
public class MyClass implements Serializable {
public int id1;
public void setId1(Integer v) { id1 = v.intValue(); };
public Integer getId1() { return new Integer(v); };
public int id2;
public void setId2(Integer v) { id2 = v.intValue(); };
public Integer getId2() { return new Integer(v); };
...
// the other 51 members
public int hashCode() {
return (id1 << 16) | id2;
}
public boolean equals() {
// ... compare all members
}
};
class mapping:
<hibernate-mapping>
<class name="...MyObject" table="mytable" >
<composite-id >
<key-property name="id1" type="int" column="id1" />
<key-property name="id2" type="int" column="id2" />
</composite-id>
... all other members/columns
public class MainTest {
int nbOfObjs = 10000;
int nbOfObjsPerTrans = 100;
public void testInsert() throws HibernateException {
Session session = HibernateUtil.currentSession();
Transaction tx = null;
boolean beginTrans = true;
boolean endTrans = false;
boolean transOpen = false;
long startTime = System.currentTimeMillis();
for (int i = 0; i < nbOfObjs; i++) {
beginTrans = (i % nbOfObjsPerTrans) == 0;
endTrans = ((i+1) % nbOfObjsPerTrans) == 0;
if (beginTrans) {
tx= session.beginTransaction();
transOpen = true;
}
// create an instance of my object
MyObject obj = new MyObject();
// obj.setId1(1234);
// obj.setId2(4567);
session.save(obj);
if (endTrans) {
tx.commit();
transOpen = false;
}
}
if (transOpen) {
tx.commit();
}
long endTime = System.currentTimeMillis();
System.out.print("testInsert, dt=" + (endTime - startTime));
}
public void testRead() throws HibernateException {
Session session = HibernateUtil.currentSession();
long startTime = System.currentTimeMillis();
for (int i = 0; i < nbOfObjs; i++) {
// create an instance of my object
MyObject obj = new Object();
// obj.setId1(1234);
// obj.setId2(4567);
session.load(MyObject.class, obj);
}
long endTime = System.currentTimeMillis();
System.out.print("testRead, dt=" + (endTime - startTime));
}
public Connection connectJDBC() throws SQLException {
Connection cnn = // open JDBC connection
return cnn;
}
public void testInsertJDBC() throws SQLException {
Connection cnn = connectJDBC();
try {
boolean beginTrans = false;
boolean endTrans = false;
boolean transOpen = false;
long startTime = System.currentTimeMillis();
for (int i = 0; i < nbOfObjs; i++) {
beginTrans = (i % nbOfObjsPerTrans) == 0;
endTrans = ((i+1) % nbOfObjsPerTrans) == 0;
if (beginTrans) {
cnn.setAutoCommit(false);
transOpen = true;
}
// create an instance of my object
MyObject obj = new MyObject();
// obj.setId1(i);
// obj.setId2(i);
// obj.set...
StringBuffer cmd = new StringBuffer();
cmd.append("insert into mytable (").
append("id1,").
append("id2,").
append("..."). // append all other columns
append(") values (");
for (int j = 0; j < 53; j++) {
if (j != 0) cmd.append(",");
cmd.append("?");
}
cmd.append(")");
String s = cmd.toString();
PreparedStatement stmt = cnn.prepareStatement(s);
stmt.setInt(1, obj.getId1());
stmt.setInt(2, obj.getId2());
stmt.setString(3, ...); // set all columns
stmt.execute();
stmt.close();
if (endTrans) {
cnn.commit();
transOpen = false;
}
}
if (transOpen) {
cnn.commit();
}
long endTime = System.currentTimeMillis();
System.out.print("testInsertJDBC, dt=" + (endTime - startTime));
} finally {
if (cnn != null) cnn.close();
}
}
public void testReadJDBC() throws SQLException {
Connection cnn = connectJDBC();
try {
long startTime = System.currentTimeMillis();
for (int i = 0; i < nbOfObjs; i++) {
// create an instance of my object
MyObject obj = new MyObject();
// obj.setId1(i);
// obj.setId2(i);
StringBuffer cmd = new StringBuffer();
cmd.append("select ").
append("id1,").
append("id2,").
append("..."). // append all other columns
append(" from mytable where ").
append(" id1=").append(i).append("and id2=").append(i);
Statement stmt = cnn.createStatement();
ResultSet rs = stmt.executeQuery(cmd.toString());
while (rs.next()) {
for (int j = 0; j < 53; j++) {
rs.getObject(j+1);
}
}
}
long endTime = System.currentTimeMillis();
System.out.print("testReadJDBC, dt=" + (endTime - startTime));
} finally {
if (cnn != null) cnn.close();
}
}
public static void main(String[] args) {
MainTest m = new MainTest();
try {
Connection cnn = m.connectJDBC();
Statement stmt = cnn.createStatement();
stmt.execute("delete from mytable");
stmt.close();
cnn.close();
if (true) {
m.testInsert();
//m.testRead();
}
if (false) {
m.testInsertJDBC();
//m.testReadJDBC();
}
}
catch (SQLException ex) {
System.err.print(ex);
}
catch (HibernateException ex) {
System.err.print(ex);
}
}
}
best regards
wolfgang