-->
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.  [ 6 posts ] 
Author Message
 Post subject: Performance problem with collections
PostPosted: Wed Jan 04, 2006 12:25 pm 
Newbie

Joined: Wed Jan 04, 2006 11:55 am
Posts: 2
Hi,

I have performance problem with deleting member from large collection

parent.getChilds().remove(child);
session.delete(child);

parent.getChilds() trigers fetch, in my case tens of thousands of rows are loaded (takes 10+ seconds). What would be my options to make it work faster - add or delete from collection without fetching _all_ its members?

Chapter "19.5.3. Bags and lists are the most efficient inverse collections"
suggest to use bags or lists but isn't there some other way?

Hibernate version:
3.1
Mapping documents:
Important part
<set
name="keyalias"
lazy="true"
inverse="true"
cascade="all-delete-orphan"
>
<cache usage="read-write" />
<key>
<column name="`OBJECT_ID`" />
</key>
<one-to-many
class="domain.hibernate.Keyalias"
/>
</set>

Code between sessionFactory.openSession() and session.close():
...
trans = sess.beginTransaction();
keyalias.getLanguage().getKeyalias().remove(keyalias);
sess.delete(keyalias);

trans.commit();


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 04, 2006 12:33 pm 
Expert
Expert

Joined: Fri Aug 19, 2005 2:11 pm
Posts: 628
Location: Cincinnati
well, if you think about it from only a database perspective, you don't have to retrieve the collection to remove it from said collection and then delete it from the db.

if your parent object exists(with the collection instantiated) in your app at the time of deletion you do need to remove it from the collection if you want the delete to be reflected immediately in your app.

however, if your parent class does not have the collection instantiated, then there is no need to remove it from the collection because the collection is built from the db.

sorry about the rant :)

if you have enough info about the object, just write a custom delete statement* and run it on the db. If the collection exists nowhere in memory at the time of deletion, then nothing else needs to be done.


* - session.createQuery("delete from ... ").executeUpdate();

_________________
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: Wed Jan 04, 2006 12:52 pm 
Regular
Regular

Joined: Thu Sep 23, 2004 11:53 am
Posts: 83
just call session.delete(child);


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 05, 2006 6:46 am 
Newbie

Joined: Wed Jan 04, 2006 11:55 am
Posts: 2
noone wrote:
just call session.delete(child);


No, i use cascade and i'll get "org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations)" if i dont remove them from collection.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 05, 2006 11:26 am 
Regular
Regular

Joined: Thu Sep 23, 2004 11:53 am
Posts: 83
I think you are recieving that exception because you have a reverse association back to the parent with cascade turned on. Which that exception would make sense because you are trying to delete the child of the parent, but the parent still has other children. I could be wrong or even way off :).


The child mapping.
<many-to-one name="Parent" class="com.acme.Parent" fetch="select" [remove cascade] >
<column name="PARENT_ID" />
</many-to-one>

I think if you remove cascade here it should work.

Hope that helps.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 05, 2006 11:52 am 
Newbie

Joined: Sun Oct 09, 2005 6:36 am
Posts: 19
Are you sure you really need this parent->child relation. Maybe you could remove it and have only a child->parent relation? Whether that is possible and really improves the performance depends on your code of course. But this would be the firtst question i would ask when i see such huge collections.

Imagine you have a user management system with users and groups. You can create a bidirectionla relation between them where both have a collection that contains the elements. This works fine if there are just a few users in a group. But what if there are 10.000 or even 100.000 users in one group? But it is very likely that you need only one side of the relation. If you want to know whether a user is in a group you can user Group.getUsers().contains(user). Or you can use User.getGroups().contains(Group). It is likely that the second solution is better as it will have about the same performance no matter how many users are in the group. Of course there are situations where it will have a worse performance, for example if you do this for every user of the 100.000 users in one big transaction. But as long as you access only a few users in one transaction (or to be exact in one hibernate session) you should probably use the second solution


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.