Adding another "HasMany" relationship slows retrieval down by two orders of magnitude.

Debbie's Avatar

Debbie

18 Jun, 2010 09:19 PM via web

I have a problem that I'm sure if caused by a lack of conceptual understanding.

I have a Company entity that has ILists of Employee and Customer entities (i.e. a company have many employees and customers, but the employees and customers only have one company).

I'm mapping it as follows:

public CompanyMap()
{

Table("Companies");
Id(x => x.Id, "COMPANY_ID");
Map(x => x.Name, "COMPANY_NAME");
HasMany<Employee>(Reveal.Member<Company>("_employees"))
    .Inverse()
    .Cascade.All()
    .Fetch.Join();
HasMany<Customer>(Reveal.Member<Company>("_customers"))
    .Inverse()
    .Cascade.All()
    .Fetch.Join();

}

What I have either the Employee or Customer relationships in the mapping, it runs in about 3 seconds. However, with both of them in, retrieval takes 5 minutes!

The (Oracle) database isn't that big. Less than 10-100 records in each table.

Any idea what I'm doing wrong?

  1. Support Staff 2 Posted by Paul Batum on 19 Jun, 2010 07:40 AM

    Paul Batum's Avatar

    Why do you have your relationships set up as fetch join? I suspect that is
    the issue - have you profiled the sql that nhibernate is generating? Have
    you tried leaving the fetch strategy as the default?

  2. 3 Posted by dcroft10 on 19 Jun, 2010 10:18 AM

    's Avatar

    I want to eager load the data, as I'll need it all.

    I haven't profiled the SQL. How would I extract it?

  3. Support Staff 4 Posted by Paul Batum on 22 Jun, 2010 09:51 AM

    Paul Batum's Avatar

    There are several ways. The first three that come to mind are:

    1. You can turn on nhibernate's "showsql" setting. This will output the SQL
    that nhibernate generates to Console.Out. Some of the example configurations
    in this page have it:

    http://wiki.fluentnhibernate.org/Database_configuration

    <http://wiki.fluentnhibernate.org/Database_configuration>2. Use your own
    database profiling tools such as sql server profiler.

    3. Use NHProf <http://nhprof.com/>

  4. 5 Posted by Dmitry on 23 Jun, 2010 02:10 PM

    Dmitry's Avatar

    You have 100 records in every table. The query will return you 100100100 = 10^6 records (.Fetch.Join();). If every table has 10 columns and 4 bytes for every column(for example) the total amount of data will be 10^61010104 = 3,72 Gb. A lot of time is needed to process, transmit and allocate such amount of data.

    Another way: 3 sec * 100 records = 300 sec = 5 min ))

    Two interesting things about Fetch.Join():

    1) If you use a CreateCriteria don't forget about Distinct() method, otherwise you will have a lot of duplicate objects.

    2) If you have an object which contains a list of "Companies" (HasMany association .Fetch.Select();) the NH will create an additional query for "Employees" when you will querying this object ignoring .Fetch.Join();

    Please, correct me if I'm wrong.

Reply to this discussion

Preview Comments are parsed with Markdown. Help with syntax

Attached Files

    You can attach files up to 10MB

    What is two plus two?