Правило о том, когда использовать опцию WITH RECOMPILE - PullRequest
13 голосов
/ 08 января 2009

Я понимаю, что опция WITH RECOMPILE заставляет оптимизатор перестраивать план запроса для сохраненных процедур, но когда вы захотите, чтобы это произошло?

Каковы некоторые практические правила, когда следует использовать параметр WITH RECOMPILE, а когда нет?

Каковы эффективные накладные расходы, связанные с простым размещением их на каждом звездочке?

Ответы [ 5 ]

16 голосов
/ 08 января 2009

Как уже говорили другие, вы не хотите просто включать WITH RECOMPILE в каждый сохраненный процесс по привычке. Тем самым вы исключите одно из основных преимуществ хранимых процедур: тот факт, что он сохраняет план запроса.

Почему это потенциально важно? Вычисление плана запроса намного более интенсивно, чем компиляция обычного процедурного кода. Поскольку синтаксис оператора SQL указывает только что вы хотите, а не (как правило) как его получить, это позволяет базе данных иметь большую степень гибкости при создании физического плана ( то есть пошаговые инструкции для фактического сбора и изменения данных). Существует много «хитростей», которые может выполнять препроцессор запросов к базе данных, и выбор, который он может сделать - какой порядок объединения таблиц, какие индексы использовать, применять ли предложения WHERE до или после объединений и т. Д.

Для простого оператора SELECT это может не иметь значения, но для любого нетривиального запроса база данных будет тратить некоторое серьезное время (измеряемое в миллисекундах, в отличие от обычных микросекунд), чтобы придумать оптимальный план. Для действительно сложных запросов он не может даже гарантировать оптимальный план, он должен просто использовать эвристику, чтобы придумать довольно хороший план. Поэтому, заставляя его перекомпилировать каждый раз, вы говорите ему, что он должен проходить этот процесс снова и снова, даже если план, который он получил, был совершенно хорош.

В зависимости от поставщика, должны быть автоматические триггеры для перекомпиляции планов запросов - например, если статистика в таблице значительно изменяется (например, гистограмма значений в определенном столбце начинает равномерно распределяться с течением времени, сильно искажается ), то БД должна это заметить и перекомпилировать план. Но, вообще говоря, разработчики базы данных будут в целом умнее, чем вы.

Как и во всем, что касается производительности, не делайте снимки в темноте; определите, где находятся узкие места, которые стоят 90% вашей производительности, и сначала решите их.

14 голосов
/ 08 января 2009

Размещение его в каждой хранимой процедуре НЕ является хорошей идеей, потому что составление плана запроса является относительно дорогой операцией, и вы не увидите никакой выгоды от кэширования и повторного использования планов запросов.

Случай динамического предложения where, созданного внутри хранимой процедуры, может быть обработан с использованием sp_executesql для выполнения TSQL вместо добавления WITH RECOMPILE к хранимой процедуре.

Другое решение (начиная с SQL Server 2005) - использовать подсказку с конкретными параметрами, используя подсказку OPTIMIZE FOR. Это хорошо работает, если значения в строках являются статическими.

В SQL Server 2008 появилась малоизвестная функция под названием "OPTIMIZE FOR UNKNOWN":

Эта подсказка направляет оптимизатор запросов использовать стандартные алгоритмы, которые у него есть всегда используется, если нет значений параметров был передан на запрос вообще. В этом случае оптимизатор будет выглядеть при всех доступных статистических данных достичь определения того, что значения локальных переменных, используемых для сформировать план запроса должен быть, вместо того, чтобы смотреть на конкретный значения параметров, которые были переданы запрос к приложению.

2 голосов
/ 20 октября 2016

обычно гораздо лучшая альтернатива WITH RECOMPILE - OPTION(RECOMPILE) как вы можете увидеть в объяснении ниже, взятом из ответа на этот вопрос здесь

Когда возникает проблема чувствительности к параметру, общий кусок на форумах и сайтах вопросов и ответов совет "использовать перекомпиляцию" (при условии другие варианты тюнинга, представленные ранее, не подходят). К несчастью, этот совет часто неверно истолковывается как добавление С RECOMPILE вариант хранимой процедуры.

Использование WITH RECOMPILE эффективно возвращает нас к SQL Server 2000 поведение, при котором вся хранимая процедура перекомпилируется на каждом выполнение. Лучшая альтернатива в SQL Server 2005 и более поздних версиях - это использовать подсказку запроса OPTION (RECOMPILE) только для оператора, который страдает от проблемы перехвата параметров. Этот запрос подсказывает результаты только в перекомпиляции проблемного высказывания; планы выполнения для других операторов в хранимой процедуре кэшируются и используются повторно как обычно.

Использование WITH RECOMPILE также означает скомпилированный план для сохраненных процедура не кэшируется. В результате информация о производительности не поддерживается в DMV, таких как sys.dm_exec_query_stats. Использование запроса подсказка вместо этого означает, что скомпилированный план может быть кэширован, а производительность информация доступна в DMV (хотя она ограничена недавнее выполнение, только для затронутого оператора).

Для экземпляров, выполняющих как минимум SQL Server 2008 build 2746 (Service Пакет 1 с накопительным обновлением 5), с помощью OPTION (RECOMPILE) есть еще значительное преимущество перед WITH RECOMPILE: только OPTION (RECOMPILE) включает оптимизацию встраивания параметров.

2 голосов
/ 08 января 2009

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

1 голос
/ 08 января 2009

Его следует использовать только при тестировании с репрезентативными данными, и контекст демонстрирует, что без него создаются неверные планы запросов (какими бы ни были возможные причины). Не думайте заранее (без тестирования), что SP не будет оптимизирован должным образом.

Единственное исключение только для ручного вызова (т.е. не кодируйте его в SP): когда вы знаете, что существенно изменили характер целевых таблиц. например TRUNCATE, насыпные грузы и т. Д.

Это еще одна возможность для преждевременной оптимизации.

Примечание: у меня много очков. Если новичок отправляет тот же ответ ниже, и вы согласны, проголосуйте за него.

...