Вопрос

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

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

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

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

Решение

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

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

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

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

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

Другие советы

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

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

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

SQL Server 2008 представил малоизвестная функция называется " ОПТИМИЗИРОВАТЬ ДЛЯ НЕИЗВЕСТНО ":

  

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

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

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

  

Когда возникает проблема чувствительности к параметру, общая часть   совет на форумах и на сайтах Q & A состоит в том, чтобы «использовать перекомпиляцию»; (при условии   другие варианты тюнинга, представленные ранее, не подходят). К несчастью,   этот совет часто неверно истолковывается как добавление С 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)   включает оптимизацию встраивания параметров.

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

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

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

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

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