2013-03-11 10 views
0

У меня есть база данных с таблицей Customer. Каждый из этих клиентов имеет внешний ключ для таблицы , которая дополнительно имеет внешний ключ для Адрес таблица (таблица переименована для простоты).NHibernate: Иерархия объектов и производительность

В NHibernate Я пытаюсь запросить таблицу клиентов, как это:

ISession session = tx.Session; 
var customers = session.QueryOver<Customer>().Where(x => x.Country == country);        
var installations = customers.JoinQueryOver(x => x.Installation, JoinType.LeftOuterJoin); 
var addresses = installations.JoinQueryOver(x => x.Address, JoinType.LeftOuterJoin); 

if (installationType != null) 
{ 
    installations.Where(x => x.Type == installationType); 
} 

return customers.TransformUsing(new DistinctRootEntityResultTransformer()).List<Customer>(); 

Какие результаты в запросе SQL аналогично (перехваченных по NHibernate Profiler):

SELECT * 
FROM Customer this_ 
     left outer join Installation installati1_ 
     on this_.InstallationId = installati1_.Id 
     left outer join Address address2_ 
     on installati1_.AddressId = address2_.Id 
WHERE this_.CountryId = 4 
     and installati1_.TypeId = 1 

Когда я выполните вышеуказанный SQL-запрос в Microsoft SQL Server Management Studio выполняется за 5 секунд, но возвращает ~ 200 000 записей. Тем не менее требуется много времени, чтобы получить Список при запуске кода. Я ждал 10 минут без каких-либо результатов. Журнал debug-log показал, что из-за иерархии объектов создается и инициируется множество объектов. Есть ли способ исправить эту проблему производительности?

ответ

1

Я не уверен, что вы пытаетесь сделать, но загрузка и сохранение 200000 записей через любой OR-сопоставитель невозможен. 200000 объектов займет много времени и памяти. В зависимости от того, что вы хотите сделать, загрузка их на страницах или запрос на обновление непосредственно в базе данных (sp или именованный запрос) могут исправить вашу производительность. Дозирование может быть сделано путем:

criteria.SetFirstResult(START).SetMaxResult(PAGESIZE); 
+0

Здесь нет сохранения/обновления, только чтение данных с помощью запроса * SELECT *. Мне нужно запросить все данные, так как они должны использоваться для отчета компании. Есть ли способ использовать NHibernate для возврата необработанных данных (примитивных типов) вместо объектов? – dhrm

+0

Не можете использовать службы отчетов или службы интеграции для получения данных из базы данных. Эти инструменты сделаны из таких отчетов. Или получить данные с поисковым вызовом. Таким образом, у вас будет больше контроля над количеством объектов в памяти. criteria.SetFirstResult (СНВ) .SetMaxResult (PAGESIZE); – Peter

0

NHibernate Profiler показывает два раза в колонке длительности х/у, с й означает время выполнения запроса и у времени для инициализации объектов. Первый шаг - определить, где лежит проблема. Если запрос выполняется медленно, получите фактический запрос, отправленный в базу данных с помощью SQL Profiler (при условии, что SQL Server) и проверьте его производительность в SSMS.

Однако, я подозреваю, что ваша проблема может быть уровнем ведения журнала. Если у вас установлен уровень регистрации в DEBUG, NHibernate будет генерировать очень подробные журналы, и это значительно повлияет на производительность.

Даже если вы можете заставить его хорошо работать с 200 000 записей, это больше, чем вы можете показать пользователю значимым образом. Вы должны использовать пейджинг/фильтрацию, чтобы уменьшить размер набора результатов.

+0

Спасибо за ваш комментарий. В настоящее время ведение журнала отладки не включено. Я сделал еще один тест, где я сделал * .Take (10000) * перед * .List <>() *, что приводит к следующей длительности в * NHibernate Profiler *: 747 мс/137202мс. Для меня это указывает на то, что проблемы связаны с инициализацией объекта. – dhrm

+0

Попробуйте удалить отдельный трансформатор. 2 + минуты кажется неоправданно медленным для меня. –

+0

Снятие отдельного трансформатора не имеет никакого значения. – dhrm