-->
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.  [ 1 post ] 
Author Message
 Post subject: Optimizing fetch of @Any association in a large collection
PostPosted: Thu Aug 21, 2014 1:47 am 
Newbie

Joined: Thu Aug 21, 2014 1:42 am
Posts: 3
I'm facing big performance issues in a large collection of entities containing an @Any association.

The only way i found to improve load time is to execute a SQL query to collect ids of one of the associated type (but could do for each different type of the Any association), then load those associated entities by batch of 200 with a criteria.

Hibernate will then populate the cache with those entities so when fetching the collection, the associations are resolved directly from the cache instead of executing a SELECT for each. Working this way, the load time is divided by 3 but still remains at 14 seconds for the full load.

Is there a better way to improve the performance?

Note : The data model cannot be changed.

Model : The parent entity has a collection of administrators (up to 8k administrator). Those administrators hold the @Any association (type A,B,C).

Code:
public class Administrator {
  some other stuffs...

  @Any(metaColumn=@Column(name="TYPE"), optional = false, fetch=FetchType.EAGER)
    @AnyMetaDef(idType="long", metaType="string", metaValues= {
        @MetaValue(targetEntity=A.class, value="A"),
        @MetaValue(targetEntity=B.class, value="B"),
        @MetaValue(targetEntity=C.class, value="C")
        })
    @JoinColumn(name="NUM")
    private RelationTypeIdentifier<Long> relation;
}


Code to preload the C entities which is the most common type of the Any association.

Code:
SQLQuery sqlQuery = getSession().createSQLQuery("select NUM as cId from SOMETABLE WHERE PARENTID = :id and TYPE = 'C'");
sqlQuery.setParameter("id", id);
sqlQuery.addScalar("cId", new LongType());
List<Long> cIds = sqlQuery.list();
List<C> result = new ArrayList<C>();
if (cIds.size() == 0) {
   return result;
}
int batchSize = 200;

int to = (cIds.size() < batchSize) ? cIds.size() : batchSize;
int from = 0;
while (cIds.size() >= to) {
   List<Long> subList = cIds.subList(from, to);
   cDao.findByIds(subList.toArray(new Long[subList.size()]));
   from += batchSize;
   to += batchSize;
}
return result;


Relying on the cache (on which you don't have much control) is certainly not the best solution so i hope someone has a better option.

I'm using hibernate 4.3.

Thank you.


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

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.