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.  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: SubselectFetch performance issue
PostPosted: Wed Jan 10, 2007 6:35 am 
Newbie

Joined: Mon Jan 08, 2007 10:14 am
Posts: 15
Location: Minsk, BY
I found an performance issue with SubselectFetch nhibernate class.

My mapping file looks like:

Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Business" namespace="Business.Entities">
   <class name="Job" table="Job">
      
      <id name="Id" column="JobId" type="Int32" unsaved-value="0">
         <generator class="identity"/>
      </id>
      <property column="InternalId" type="string" name="Title" not-null="true" />
      <property column="Description" type="String" name="Description" not-null="true" />
      <property column="Url" type="String" name="Url" not-null="true" />

    <bag name="CategoryIds" table="JobCategory" fetch="subselect" inverse="true" lazy="true" generic="true" >
      <key column="JobId" />
      <element column="CategoryId" type="Int32"/>
    </bag>

    <bag name="RegionIds" table="JobRegion" fetch="subselect" inverse="true" lazy="true" generic="true" >
      <key column="JobId" />
      <element column="RegionId" type="Int32"/>
    </bag>

   </class>
</hibernate-mapping>


I'm trying to load 1000 objects from table Job using a query like:
Code:
IQuery query = Session.CreateQuery("from Job j where j.Id in (:id_list)");
query.SetParameterList("id_list", jobIds);
IList<Job> result = query.List<Job>();

NHibernateUtil.Initialize(result[0].CategoryIds);
NHibernateUtil.Initialize(result[0].RegionIds);


Nhibernate generates three expected queries that take about only ~10% of all query execution time.

Code:
select job0_.JobId as JobId0_, job0_.Title as Title0_, from Job job0_ where (job0_.JobId in(@p0 , @p1 , ... , @p999))

SELECT categoryid0_.JobId as JobId__0_, categoryid0_.CategoryId as CategoryId0_ FROM JobCategory categoryid0_ WHERE categoryid0_.JobId in (select job0_.JobId from Job job0_ where (job0_.JobId in(@p0 , @p1 , ..., @p999)));

SELECT regionids0_.JobId as JobId__0_, regionids0_.RegionId as RegionId0_ FROM JobRegion regionids0_ WHERE regionids0_.JobId in (select job0_.JobId from Job job0_ where (job0_.JobId in(@p0 , @p1 , @p2 , ..., @p999)));


But almost all other time ~70% is taken by SubselectFetch constructor, which is executed in CreateSubselects method.
Is it correct behaviour?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 10, 2007 1:24 pm 
Contributor
Contributor

Joined: Sat Sep 24, 2005 11:25 am
Posts: 198
Can you check what it is doing there. I don't believe that this is an appropriate behavior.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 10, 2007 1:54 pm 
Newbie

Joined: Mon Jan 08, 2007 10:14 am
Posts: 15
Location: Minsk, BY
Image


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 10, 2007 2:36 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Created NH-859 for this.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 21, 2007 1:03 pm 
Newbie

Joined: Sun Jan 21, 2007 12:10 pm
Posts: 2
Almas wrote:
Image


What tool are you using to generate this image?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 21, 2007 2:10 pm 
Contributor
Contributor

Joined: Sat Sep 24, 2005 11:25 am
Posts: 198
dotTrace from JetBrains.
Highly recommended


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jan 22, 2007 10:06 am 
Newbie

Joined: Sun Jan 21, 2007 12:10 pm
Posts: 2
Ayende Rahien wrote:
dotTrace from JetBrains.
Highly recommended

Hey, I'm logged and can't rate your post? What should I do?
Or that is because I'm not the creator of the post?
TIA


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 07, 2007 11:07 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Almas, can you try profiling the latest version from SVN? A patch was applied that may solve the problem.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 20, 2007 6:23 pm 
Newbie

Joined: Mon Jan 08, 2007 10:14 am
Posts: 15
Location: Minsk, BY
sergey, can you provide me the latest binaries?
i have no Subversion client.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 21, 2007 2:52 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
I'm going to release the next version (1.2.0.CR1) in a week or so, maybe less.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 04, 2007 11:34 am 
Newbie

Joined: Mon Jan 08, 2007 10:14 am
Posts: 15
Location: Minsk, BY
It seems that there is almost no difference.
Image


Top
 Profile  
 
 Post subject:
PostPosted: Sun Mar 04, 2007 10:09 pm 
Regular
Regular

Joined: Tue Aug 08, 2006 4:28 am
Posts: 96
Location: Hong Kong
I see a difference in the number of calls to SubselectFetch..ctor

In the first test, SubselectFetch..ctor was called 1000 times, which last for 27s. In the second test, it is called 2000 times and lasts for 33 seconds.

I am just curious if the test cases are identical. Or the NHibernate implementation is changed.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 05, 2007 3:48 am 
Newbie

Joined: Mon Jan 08, 2007 10:14 am
Posts: 15
Location: Minsk, BY
The second test is slightly different, but the main idea that it shows a time percentage of function calls.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 05, 2007 3:54 am 
Newbie

Joined: Mon Jan 08, 2007 10:14 am
Posts: 15
Location: Minsk, BY
The initial code.
Code:
static void Main(string[] args)
{
   JobService js = new JobService();

   IList<int> ids = js.GetActiveJobIds();
   IList<Job> jobs = js.Get(new List<int>(ids).GetRange(0, 1000), true);
}


A code that uses NHibernate.
Code:
  public class JobService
  {
    public IList<Job> Get(List<int> jobIds, bool forceLoadChildren)
    {
      using (PersistenceManager pm = new PersistenceManager())
      {
        IQuery query = pm.Session.CreateQuery("from Job j where j.Id in (:id_list)");

        query.SetParameterList("id_list", jobIds);

        IList<Job> result = query.List<Job>();

        if (forceLoadChildren && (result.Count > 0))
        {
          NHibernateUtil.Initialize(result[0].CategoryIds);
          NHibernateUtil.Initialize(result[0].RegionIds);
        }

        pm.Flush();

        return result;
      }
    }

    public IList<int> GetActiveJobIds()
    {
      using (PersistenceManager pm = new PersistenceManager())
      {
        IQuery query = pm.Session.CreateQuery("select j.Id from Job j where j.Status=:Status");

        query.SetEnum("Status", JobStatuses.Active);

        IList<int> result = query.List<int>();
        pm.Flush();
        return result;
      }
    }
  }


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 05, 2007 5:03 am 
Regular
Regular

Joined: Tue Aug 08, 2006 4:28 am
Posts: 96
Location: Hong Kong
I don't know when the performance of subselect would get fixed. In the meantime, would you try
Code:
fetch="select"
? Subselect will not out-perform select when you have all the Job.Id's (here I mean SQL performance).


To further optimize the NH performance, you may add
Code:
batch-size="X"
. But to make this work, you need to initialize all collections. I.e.
Code:
NHibernateUtil.Initialize(result[i].CategoryIds);
for all i's. You may need to tune the value of "X" to get the best result.

Hopes this helps


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next

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.