Entity Framework 4.2 exec sp_executesql не использует индексы (сниффинг параметров) - PullRequest
24 голосов
/ 14 февраля 2012

Я сталкиваюсь с некоторыми серьезными проблемами с производительностью при использовании простых SQL-запросов, генерируемых Entity Framework (4.2), работающих на SQL Server 2008 R2.В некоторых ситуациях (но не во всех) EF использует следующий синтаксис:

exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE', @param1...

В других ситуациях просто выполняет необработанный SQL с предоставленными параметрами, запеченными в запросе.Проблема, с которой я сталкиваюсь, заключается в том, что запросы, выполняемые с помощью sp_executesql, игнорируют все индексы в моих целевых таблицах, что приводит к чрезвычайно низкому уровню выполнения запроса (подтвержденного проверкой плана выполнения в SSMS).

Через некоторое времяПохоже, что проблема может быть вызвана «анализом параметров».Если я добавлю подсказку запроса OPTION (RECOMPILE) следующим образом:

exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE OPTION(RECOMPILE)', @param1...

Используются индексы на целевых таблицах, и запрос выполняется очень быстро.Я также пытался включить флаг трассировки, используемый для отключения сниффинга параметров (4136) в экземпляре базы данных (http://support.microsoft.com/kb/980653),, однако это не оказало никакого влияния.

Это оставляет меняс несколькими вопросами:

  1. Есть ли в любом случае добавить подсказку запроса OPTION (RECOMPILE) к SQL, сгенерированному Entity Framework?
  2. Есть ли в любом случае запретить Entity Framework использовать execsp_executesql, а вместо этого просто запустить сырой SQL?
  3. Кто-нибудь еще сталкивался с этой проблемой? Любые другие советы / подсказки?

Дополнительная информация:

  1. Я перезапустил экземпляр базы данных через SSMS, однако я попытаюсь перезапустить службу из консоли управления службами.
  2. Параметризация установлена ​​на SIMPLE (is_parameterization_forced: 0)
  3. Оптимизация для рабочих нагрузок adhoc имеет следующие настройки
    • значение: 0
    • минимум: 0
    • максимум: 1
    • value_in_use: 0
    • is_dynamic: 1
    • is_advanced: 1

Следует также упомянуть, что если я перезапущу службу SQL Server через консоль управления службами ПОСЛЕ включенияфлаг трассировки 4136 с приведенным ниже сценарием, по-видимому, фактически очищает флаг трассировки ... возможно, я должен сделать это по-другому ...

DBCC TRACEON(4136,-1)

Ответы [ 2 ]

7 голосов
/ 18 марта 2013

ТЛ; др

update statistics


У нас был запрос delete с одним параметром (первичным ключом), который завершался ~ 7 секунд при вызове через EF и sp_executesql. Выполнение запроса вручную с параметром, встроенным в первый аргумент sp_executesql, ускорило выполнение запроса (~ 0,2 секунды). Добавление option (recompile) тоже сработало. Конечно, эти два обходных пути нам недоступны, так как мы использовали EF.

Вероятно, из-за каскадных ограничений внешнего ключа план выполнения для долгосрочного запроса был, ну ... огромным. Когда я посмотрел на план выполнения в SSMS, я заметил, что стрелки между различными шагами в некоторых случаях были шире, чем в других, что, возможно, указывает на то, что SQL Server испытывал затруднения при принятии правильных решений. Это заставило меня задуматься о статистике. Я посмотрел на шаги в плане выполнения, чтобы увидеть, какая таблица была задействована в подозрительных шагах. Затем я запустил update statistics Table для этого стола. Затем я повторно запустил плохой запрос. И я снова запустил его. И снова просто чтобы убедиться. Это сработало. Наш перфоманс вернулся к норме. (Все еще несколько хуже, чем не sp_executesql производительность, но эй!)

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

5 голосов
/ 02 мая 2012

На данный момент я бы порекомендовал:


Установите для параметра оптимизации для специальных рабочих нагрузок значение true.

EXEC sp_configure 'show advanced', 1;
GO
RECONFIGURE WITH OVERRIDE;
GO
EXEC sp_configure 'optimize for ad hoc', 1;
GO
RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure 'show advanced', 0;
GO
RECONFIGURE WITH OVERRIDE;
GO

Если через какое-то время эта настройка, похоже, не помогла, только тогда я попробую дополнительную поддержку флага трассировки. Они обычно зарезервированы как последнее средство. Установите флаг трассировки с помощью командной строки через диспетчер конфигурации SQL Server, в отличие от окна запроса и с использованием глобального флага. Смотри http://msdn.microsoft.com/en-us/library/ms187329.aspx

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