-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 
Author Message
 Post subject: Performance improvement with batch updates
PostPosted: Tue Jan 24, 2006 4:29 pm 
Newbie

Joined: Tue Jan 24, 2006 12:30 pm
Posts: 4
We are having some real performance problems, due to the large number of records we need to process. One example is where we need to modify a large number (say 10,000) entity beans. Here is sample code using the entity manager:

void moveDogs(List<Integer> dogIds, Owner newOwner)
{
for (Integer dogId : dogIds)
{
Dog dog = em.find(Dog.class, dogId);

dog.setOwner(newOwner);
em.merge(dog);
}
}

To process 5,000 records, the above takes 192 seconds. Doing the exact same thing, using prepared statements and a batch update, takes less than one second (see code below). Obviously I would prefer the former code, but our users just won't stand for that performance. My question is, are there any plans to have this kind of optimization built in to hibernate? (Where it would internally do the batch update).

void moveDogs(List<Integer> dogIds, Owner newOwner)
{
int newOwnerId = newOwner.getId();

try
{
HibernateSession hs = (org.jboss.ejb3.entity.HibernateSession) em;
Session session = hs.getHibernateSession();
Connection connection = session.connection();

PreparedStatement statement = connection.prepareStatement("update dog d set d.owner_id = ? where d.id = ?");

for (Integer dogId : dogIds)
{
statement.setInt(1, ownerId);
statement.setInt(2, dogId);
statement.addBatch();
}

statement.executeBatch();
}
catch (SQLException e)
{
logger.error(e);
}
}


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 24, 2006 5:37 pm 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
The functionality you want already exists in hibernate; it's called HQL queries.

session.createQuery("...").executeUpdate();

http://www.hibernate.org/hib_docs/v3/re ... ryhql-bulk

_________________
Chris

If you were at work doing this voluntarily, imagine what you'd want to see to answer a question.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 24, 2006 5:37 pm 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
The functionality you want already exists in hibernate; it's called HQL queries.

session.createQuery("...").executeUpdate();

http://www.hibernate.org/hib_docs/v3/re ... ryhql-bulk

_________________
Chris

If you were at work doing this voluntarily, imagine what you'd want to see to answer a question.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 24, 2006 5:52 pm 
Newbie

Joined: Tue Jan 24, 2006 12:30 pm
Posts: 4
We tried going that route, but the trick is there is no single query that can do the job. We need to execute an update on a list of IDs passed in. We also tried a query using "where in()" but the maximum number of entries that can handle is 1000, and we are doing upwards of 20,000.

It seems the batchUpdate is the only way we can get it done with one call to the database, which is how we are getting the great performance now.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 24, 2006 6:04 pm 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
hibernate automatically does many queries through a batch. Have you tried putting it inside of a transaction and committing only after all your queries have been created?

f.y.i. I've never tried this, but I don't see why it wouldn't work.
Code:
transaction tx = session.startTransaction();
for ..

session.create("update bla bla bla").executeUpdate();


}

tx.commit();
tx.close();

_________________
Chris

If you were at work doing this voluntarily, imagine what you'd want to see to answer a question.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 24, 2006 6:56 pm 
Newbie

Joined: Tue Jan 24, 2006 12:30 pm
Posts: 4
Yes, we have. It is just one transaction, but (I think) 5,000 individual update statements if we do it that way. At least that is what I attribute the slow down to.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 24, 2006 11:19 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
try either of these two:
1) actually enable jdbc-level batching in Hibernate and then do the iteration code you do in your #1
2) segment the incoming id list into "workable sizes" and then do HQL update statements based on the segmented ids...


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 25, 2006 4:49 pm 
Newbie

Joined: Tue Jan 24, 2006 12:30 pm
Posts: 4
For option 1), is this how you enable it?

<property name="hibernate.jdbc.batch_size" value="10000" />

We've tried that, and it didn't change the performance.

For option 2), yes, I think that is a workable (we've done it in another case) and I imagine the performance would be comparable to the prepared statements. Thanks.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.