Запросы, выполняемые из Nhibernate, являются медленными, но из ADO.NET - быстрыми. - PullRequest
12 голосов
/ 13 октября 2011

У меня есть запрос в приложении MVC, выполнение которого занимает около 20 секунд (с использованием NHibernate 3.1).Когда я выполняю запрос вручную в Management studio, это занимает 0 секунд.

Я видел похожие вопросы на SO о проблемах, похожих на эту, поэтому я продвинулся на шаг дальше.

Я перехватил запрос с помощью Sql Server Profiler и выполнил запрос с помощью ADO.NET в моем приложении.

Запрос, полученный от Profiler, выглядит примерно так: "exec sp_executesql N'select ...."

Мой код ADO.NET:

SqlConnection conn = (SqlConnection) NHibernateManager.Current.Connection;

var query = @"<query from profiler...>";
var cmd = new SqlCommand(query, conn);

SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return RedirectToAction("Index");

Этот запрос также очень быстрый и не требует времени для выполнения.

Кроме того, я видел кое-что очень странное вПрофилировщик.Запрос, выполненный из NH, имеет следующую статистику:

читает: 281702 пишет: 0

Запрос из ADO.NET:

читает: 333 пишет: 0

У кого-нибудь есть подсказка?Могу ли я предоставить какую-либо информацию для диагностики проблемы?

Я думал, что это может быть связано с некоторыми настройками соединения, но версия ADO.NET использует то же соединение от NHibernate.

Заранее спасибо

ОБНОВЛЕНИЕ:

Я использую NHibernate LINQ.Запрос является огромным, но это запрос на пейджинг, из которого выбирается всего 10 записей.

Параметры, которые передаются в "exec sp_executesql":

@ p0 int, @ p1 datetime, @ p2 datetime, @ p3 bit, @ p4 int, @ p5 int

@ p0 = 10, @ p1 = '2009-12-01 00:00:00', @ p2 = '2009-12-31 23:59:59 ', @ p3 = 0, @ p4 = 1, @ p5 = 0

Ответы [ 4 ]

8 голосов
/ 21 октября 2011

У меня были ADO.NET и NHibernate, использующие разные планы запросов, и я перенес влияние перехвата параметров на версию NH.Зачем?Потому что ранее я делал запрос с небольшим интервалом дат, и сохраненный план запроса был оптимизирован для него.

Впоследствии, при запросах с большим интервалом дат использовался сохраненный план, и для получения результата потребовались годы.

Я подтвердил, что это на самом деле проблема, потому что простое:

DBCC FREEPROCCACHE -- clears the query-plan cache

снова сделал мой запрос быстрым.

Я нашел 2 способа решить эту проблему:

  • Внедрение в запрос «option (перекомпилировать)», используяNH Interceptor
  • Добавление фиктивного предиката к моему выражению NH Linq, например: query = query.Where(true), когда ожидаемый набор результатов был небольшим (с интервалом дат).Таким образом, будут созданы два разных плана запросов, один для больших наборов данных и один для небольших наборов.

Я пробовал оба варианта, и оба работали, но выбрали второй подход.Это немного хакерский , но в моем случае он работает очень хорошо, потому что данные распределены по дате равномерно.

7 голосов
/ 24 февраля 2012

У меня была та же проблема, что и у ОП.Я попробовал предложение @ psousa о введении «опции (перекомпиляции)», что улучшило мою производительность.Но в конце концов я обнаружил, что простое обновление статистики на SQL Server помогло мне.

update statistics tablename;

Я закончил тем, что отступил от своего кода, чтобы ввести «option (пересобрать)».Я понимаю, что это может быть ответ не для всех, но хотел бы поделиться, поскольку это было причиной моих проблем.

2 голосов
/ 13 октября 2011

Посмотрите на параметры, предоставляемые хранимой процедуре sp_executesql. Если параметры поставляются в виде nvarchar (N'value ') и столбцы, на которые они ссылаются, являются varchar, SQL Server будет использовать очень неэффективный план запросов. Это было основной причиной всех проблем с производительностью, которые у меня были, с такими симптомами (медленно в приложении, быстро в SSMS).

0 голосов
/ 13 октября 2011

Вы не указали свой запрос или размер его набора результатов, но есть проблема с извлечением большого количества объектов с помощью nHibernate.
В основном, время для "гидратации" объектов - это то, что занимает столько времени.1002 * Вы можете попробовать включить оптимизатор отражений или использовать IStatelessSession.
см. Некоторые предложения, которые я получил здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...