Подтвердить что ты не робот

Запрос, выполняемый из Nhibernate, медленный, но из ADO.NET быстро

У меня есть запрос в моем приложении MVC, для завершения которого требуется около 20 секунд (с использованием NHibernate 3.1). Когда я запускаю запрос вручную в студии управления, он занимает 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");

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

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

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

Один из ADO.NET:

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

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

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

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

UPDATE:

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

Параметры, которые передаются "exec sp_executesql", следующие:

@p0 int, @p1 datetime, @p2 datetime, @p3 бит, @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

4b9b3361

Ответ 1

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

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

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

DBCC FREEPROCCACHE -- clears the query-plan cache

снова выполнил мой запрос.

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

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

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

Ответ 2

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

update statistics tablename;

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

Ответ 3

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

Ответ 4

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