Монументальная разница во времени выполнения между запросами при использовании подсказки для перекомпилирования запросов

dba.stackexchange https://dba.stackexchange.com/questions/15269

Вопрос

У меня есть два почти идентичных запроса, работающие на одном и том же экземпляре SQL Server 2005:

  1. Первый - оригинал SELECT Запрос, созданный LINQ (я знаю, я знаю ... Я не разработчик приложений, только DBA :).
  2. Второй точно такой же, как и первый, добавил OPTION (RECOMPILE) в конце.

Больше ничего не изменилось.

Первый занимает 55 секунд каждый раз, когда он работает.
Второй занимает 2 секунды.

Оба набора результатов идентичны.

Зачем этот намек приносит такой драматический прирост производительности?

Книги онлайн вход RECOMPILE не предлагает много подробного объяснения:

Инструктирует двигатель базы данных SQL Server отбросить план, сгенерированный для запроса после его выполнения, заставив оптимизатор запроса отменять план запроса в следующий раз, когда будет выполнен тот же запрос. Без указания перекомпиляции, планы запросов двигателя базы данных и повторно используют их. При составлении планов запросов в запросе Recompile подсказка использует текущие значения любых локальных переменных в запросе и, если запрос находится внутри хранимой процедуры, текущие значения передаются в любые параметры.

Recompile является полезной альтернативой созданию хранимой процедуры, которая использует предложение с Recompile, когда должно быть перекомпилировано только подмножество запросов внутри хранимой процедуры, а не всей хранимой процедуры. Для получения дополнительной информации см. Перекомпиляцию хранимых процедур. Recompile также полезен, когда вы создаете руководства по планам. Для получения дополнительной информации см. Оптимизация запросов в развернутых приложениях с помощью плановых руководств.

Поскольку в моем запросе много локальных переменных, я предполагаю, что SQL Server может (серьезно) оптимизировать его, когда я использую OPTION (RECOMPILE) Подсказка запроса.

Везде я смотрю, как люди говорят OPTION (RECOMPILE) необходимо избегать. Объяснение для этого обычно заключается в том, что использование этого SQL Server не может повторно использовать этот план выключения и, следовательно, должен тратить время на перекомплектование его каждый раз.
(Но), учитывая гигантское преимущество в производительности, я склонен думать, что использование этого запроса на этот раз будет хорошей вещью.

Мне это использовать? Если нет, то есть ли способ заставить SQL Server использовать лучший план выполнения без этого подсказка и без изменения приложения?

Это было полезно?

Решение

Как задокументировано в статье Статистика, используемая оптимизатором запроса в Microsoft SQL Server 2005

Если вы используете локальную переменную в предикате запроса вместо параметра или буквального, оптимизатор прибегает к оценке пониженного качества или предположение о селективности предиката. Используйте параметры или литералы в запросе вместо локальных переменных

Когда оптимизатор не имеет полезной статистики вообще для столбца, он будет предполагать что = предикат будет соответствовать 10% рядов, BETWEEN 9%и любой из >, >=, < and <= будет соответствовать 30%. Если есть статистика столбцов = Предикат будет рассматриваться по -разному, как показано ниже.

Даже когда локальные переменные используются в запросе, оценка, которая лучше, чем предположение, используется в случае предикатов равенства. Селективность для условий формы "@local_variable = column_name«Оценивается с использованием частоты среднего значения из гистограммы для Column_Name. Так, например, если столбец Column_Name содержит все уникальные значения, то оценка селективности 1/(number of unique values in column) будет использоваться, что является точным.

Так что это по сути, то же самое, что и для использования для OPTIMIZE FOR (UNKNOWN). Анкет Это вполне может быть более точным, чем плоская 10% Угадайте, но это не адаптировано к конкретным значениям, которые вы запрашиваете.

Чтобы заставить SQL Server оптимизировать запрос каждый раз, когда он запускается, и используйте значения локальных переменных для оценки кардинальности и стоимости во время оптимизации запроса, добавьте RECOMPILE Запрос намекает на запрос.

С использованием RECOMPILE Предположительно, вы получаете более точные оценки кардинальности и, следовательно, другой план с согласованными ордерами/ типами соединений, более подходящих для количества строк, возвращаемых из разных частей вашего фактического запроса.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top