Как использовать ToFuture в nhibernate? - PullRequest
3 голосов
/ 18 ноября 2011

Скажите, у меня есть эти запросы

// Linq 
    var allRecords = session.Query<Table1P>().FetchMany(x => x.Table2).FetchMany(x => x.Table3).FetchMany(x => x.Table4).FetchMany(x => x.Table6).ToList();

// Hql
string hqlQuery = @"from Table1 tbl1
                                left join fetch tbl1.Table2 tbl2
                                left join fetch tbl1.Table3
                                left join fetch tbl1.Table4
                                left join fetch tbl1.Table6
                                left join fetch tbl2.Table5s";

В приведенных выше случаях мне нужно выполнить все эти объединения, чтобы остановить отложенную загрузку и выполнить загрузку с нетерпением. Теперь в профилировщике nhibernate появится предупреждение о слишком большом числе соединений.

http://nhprof.com/Learn/Alerts/TooManyJoins

Так что один из способов остановить это оповещение - это разорвать соединения. и сделать несколько запросов. Это то, что я пытаюсь сделать. Однако в то же время я читал о будущей функции, которая, как мне кажется, позволила бы мне разбить запрос (остановить слишком много соединений), но все же выполнить его за один раз.

Редактировать

Я пробовал ToFuture и обнаруживал его медленнее, когда пытался ограничить объем возвращаемых данных (если я пытаюсь вернуть все обратно, он работает быстрее, так как он не падает).

  var allRecords = session.Query<Table1P>().FetchMany(x => x.Table2).FetchMany(x => x.Table3).FetchMany(x => x.Table4).FetchMany(x => x.Table6).Take(3000).ToList();

// result (2.731 seconds), row count 3000, duration 8 ms/ 2013 ms

select TOP (3000 /* @p0 */) table1p0_.Id        as Id1_0_,
                 table2x1_.Id        as Id2_1_,
                 table3x2_.Id        as Id3_2_,
                 table4x3_.Id        as Id4_3_,
                 table6x4_.Id        as Id6_4_,
                 table1p0_.F1        as F2_1_0_,
                 table1p0_.F2        as F3_1_0_,
                 table1p0_.F3        as F4_1_0_,
                 table2x1_.F1        as F2_2_1_,
                 table2x1_.F2        as F3_2_1_,
                 table2x1_.F3        as F4_2_1_,
                 table2x1_.Table1_id as Table5_2_1_,
                 table2x1_.Table1_id as Table5_0__,
                 table2x1_.Id        as Id0__,
                 table3x2_.F1        as F2_3_2_,
                 table3x2_.F2        as F3_3_2_,
                 table3x2_.F3        as F4_3_2_,
                 table3x2_.Table1_id as Table5_3_2_,
                 table3x2_.Table1_id as Table5_1__,
                 table3x2_.Id        as Id1__,
                 table4x3_.F1        as F2_4_3_,
                 table4x3_.F2        as F3_4_3_,
                 table4x3_.F3        as F4_4_3_,
                 table4x3_.Table1_id as Table5_4_3_,
                 table4x3_.Table1_id as Table5_2__,
                 table4x3_.Id        as Id2__,
                 table6x4_.F1        as F2_6_4_,
                 table6x4_.F2        as F3_6_4_,
                 table6x4_.F3        as F4_6_4_,
                 table6x4_.Table1_id as Table5_6_4_,
                 table6x4_.Table1_id as Table5_3__,
                 table6x4_.Id        as Id3__
from   Table1 table1p0_
       left outer join [Table2] table2x1_
         on table1p0_.Id = table2x1_.Table1_id
       left outer join [Table3] table3x2_
         on table1p0_.Id = table3x2_.Table1_id
       left outer join [Table4] table4x3_
         on table1p0_.Id = table4x3_.Table1_id
       left outer join [Table6] table6x4_
         on table1p0_.Id = table6x4_.Table1_id

Использование ToFuture

// result (4.808 seconds), row count 6944 / 75/ 374, duration 1ms / 4022 ms

                // will load the Entities with Table2 fetched
                var allRecords = session.Query<Table1P>()
                    .FetchMany(x => x.Table2)
                    .ToFuture()
                    .Take(3000);

                // will load the Entities with Table3 fetched
                session.Query<Table1P>()
                    .FetchMany(x => x.Table3)
                    .ToFuture();

                // will load the Entities with Table4 fetched
                session.Query<Table1P>()
                    .FetchMany(x => x.Table4)
                    .ToFuture();

                // will load the Entities with Table6 fetched
                session.Query<Table1P>()
                    .FetchMany(x => x.Table6)
                    .ToFuture();

                // will trigger all queries at once and the session cache will make sure,
                // that the results of all queries fill the same Entities
                allRecords.ToList();


select table1p0_.Id        as Id1_0_,
       table2x1_.Id        as Id2_1_,
       table1p0_.F1        as F2_1_0_,
       table1p0_.F2        as F3_1_0_,
       table1p0_.F3        as F4_1_0_,
       table2x1_.F1        as F2_2_1_,
       table2x1_.F2        as F3_2_1_,
       table2x1_.F3        as F4_2_1_,
       table2x1_.Table1_id as Table5_2_1_,
       table2x1_.Table1_id as Table5_0__,
       table2x1_.Id        as Id0__
from   Table1 table1p0_
       left outer join [Table2] table2x1_
         on table1p0_.Id = table2x1_.Table1_id;



select table1p0_.Id        as Id1_0_,
       table3x1_.Id        as Id3_1_,
       table1p0_.F1        as F2_1_0_,
       table1p0_.F2        as F3_1_0_,
       table1p0_.F3        as F4_1_0_,
       table3x1_.F1        as F2_3_1_,
       table3x1_.F2        as F3_3_1_,
       table3x1_.F3        as F4_3_1_,
       table3x1_.Table1_id as Table5_3_1_,
       table3x1_.Table1_id as Table5_0__,
       table3x1_.Id        as Id0__
from   Table1 table1p0_
       left outer join [Table3] table3x1_
         on table1p0_.Id = table3x1_.Table1_id;



select table1p0_.Id        as Id1_0_,
       table4x1_.Id        as Id4_1_,
       table1p0_.F1        as F2_1_0_,
       table1p0_.F2        as F3_1_0_,
       table1p0_.F3        as F4_1_0_,
       table4x1_.F1        as F2_4_1_,
       table4x1_.F2        as F3_4_1_,
       table4x1_.F3        as F4_4_1_,
       table4x1_.Table1_id as Table5_4_1_,
       table4x1_.Table1_id as Table5_0__,
       table4x1_.Id        as Id0__
from   Table1 table1p0_
       left outer join [Table4] table4x1_
         on table1p0_.Id = table4x1_.Table1_id;



select table1p0_.Id        as Id1_0_,
       table6x1_.Id        as Id6_1_,
       table1p0_.F1        as F2_1_0_,
       table1p0_.F2        as F3_1_0_,
       table1p0_.F3        as F4_1_0_,
       table6x1_.F1        as F2_6_1_,
       table6x1_.F2        as F3_6_1_,
       table6x1_.F3        as F4_6_1_,
       table6x1_.Table1_id as Table5_6_1_,
       table6x1_.Table1_id as Table5_0__,
       table6x1_.Id        as Id0__
from   Table1 table1p0_
       left outer join [Table6] table6x1_
         on table1p0_.Id = table6x1_.Table1_id;

Запросы и время, полученные от профилировщика nhibernate. Тест был запущен, запустив его один раз с одним из наборов кода, записав результаты, остановив сервер разработки .net и затем запустив другой набор кода.

Таблица 1 - 6200 строк Таблица2 - 744 строки Таблица3 - 75 строк Таблица4 - 374 строки Таблица6 - 300 строк

Практически в таблице 1 есть один ко многим ко всем остальным столам.

1 Ответ

2 голосов
/ 21 ноября 2011
// will load the Entities with Table2 fetched
var allRecords = session.Query<Table1P>()
    .FetchMany(x => x.Table2)
    .ToFuture();

// will load the Entities with Table3 fetched
session.Query<Table1P>()
    .FetchMany(x => x.Table3)
    .ToFuture();

// will load the Entities with Table4 fetched
session.Query<Table1P>()
    .FetchMany(x => x.Table4)
    .ToFuture();

// will load the Entities with Table6 fetched
session.Query<Table1P>()
    .FetchMany(x => x.Table6)
    .ToFuture();

// will trigger all queries at once and the session cache will make sure,
// that the results of all queries fill the same Entities
allRecords.ToList();

изменить

       .ToFuture()
       .Take(3000);

на

       .Take(3000);
       .ToFuture()

Обновление:

// Hql
var allRecords = session.CreateQuery("from Table1 left join fetch tbl1.Table2")
    .ToFuture<Table1>();

...

Странно, что это медленнее, чем большое соединение.Я не могу проверить здесь прямо сейчас.Возможно, при не столь большом количестве строк в БД издержки для нескольких наборов результатов больше, чем у расширенных соединений.Можете ли вы попробовать с большим количеством данных в БД?

...