Оптимизация: перемещение объявлений переменных в начало вашей процедуры

15

Работая над оптимизацией некоторых хранимых процедур, я сел с администратором базы данных и прошел через некоторые хранимые процедуры с высокой блокировкой и / или высокой активностью чтения / записи.

DBA упомянул одну вещь: я должен объявить все переменные (особенно TABLEте) в начале хранимой процедуры, чтобы избежать перекомпиляции.

Это первое, что я услышал об этом, и искал подтверждение, прежде чем вернуться ко всем различным хранимым процедурам, которые у нас есть. Он называл это «поздним просмотром кода», и перекомпиляция блокировала схему, которая будет учитывать блокировку.

Уменьшает ли перемещение всех объявлений переменных в начало вашей хранимой процедуры перекомпиляцию?

brad.v
источник

Ответы:

18

Нет.

Раньше либо это было правдой давным-давно (а теперь нет, по крайней мере с SQL Server 2000), либо это никогда не было правдой, и ваш администратор баз данных просто перепутал свою рекомендацию со следующей :

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

Вы можете найти другое объяснение причин этой рекомендации на этой странице .

Если мы посмотрим на этот Microsoft KB , то увидим, что причиной перекомпиляции хранимой процедуры может быть одна из следующих причин (SQL Server 2005+):

  1. Схема изменилась.
  2. Статистика изменилась.
  3. Перекомпилируй ДНР.
  4. Заданная опция изменена.
  5. Изменена временная таблица.
  6. Удаленный набор строк изменен.
  7. Для просмотра химическая завивка изменена.
  8. Среда уведомления о запросах изменена.
  9. MPI вид изменился.
  10. Параметры курсора изменены.
  11. С опцией перекомпиляции.

Объявление переменной - даже табличной переменной (то есть @table_variable) - не может инициировать ни одно из этих событий, очевидно, потому что объявление переменной не считается как DDL . Переменная (даже табличная переменная) - это временный объект, используемый исключительно для программирования на T-SQL. Вот почему табличные переменные не получают статистики и не связаны транзакциями . Объявление переменной (табличной или нет) не может вызвать перекомпиляцию процедуры.

Однако создание временной таблицы (то есть #temp_table) или индекса - это DDL, который влияет на физическое определение базы данных. Временные таблицы и индексы являются «реальными» объектами со статистикой и контролем транзакций, поэтому их создание может вызвать любое из событий 1, 2 или 5 в списке выше и, таким образом, вызвать перекомпиляцию proc.

Ник Чаммас
источник
3

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

Чтобы разобраться в части вопроса «о чем думает мой администратор баз данных», единственное, что я могу придумать (кроме того, что Ник считает, что они думают о том, как что-то было раньше), возможно, они говорили о параметре Sniffing (см. Вариант 2 по этой ссылке на простой разговор)

О вашей блокировке -> Если вы видите истинную блокировку, это не тот тип состязания за блокировку компиляции, о котором говорит ваш администратор баз данных. Хотя верно то, что на это влияют определенные вещи (например, не таблицы, определяющие схему, не схема, которая квалифицирует ваши вызовы хранимых процедур), это, конечно, не является причиной высокого чтения и, вероятно, не является причиной вашей блокировки. Вы должны определенно сделать все возможное, чтобы избежать этих блокировок компиляции. Но я бы смотрел на настройку и оптимизацию остальной части кода хранимой процедуры как на более важную задачу, чем беспокоиться о том, где находятся переменные. Вы также можете прочитать Как определить и устранить блокировки компиляции, если хотите убедиться, что у вас нет проблем здесь.

Опубликуйте эти примеры до и после, и мы увидим, на что направляет администратор баз данных.

Майк Уолш
источник