Хранимая процедура ALTER (без изменений) заставляет ее работать в 20 раз медленнее - PullRequest
2 голосов
/ 11 марта 2019

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

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

Вот процесс:

  1. Удалить все данные из таблицы назначения
  2. Запустите хранимую процедуру и передайте в JSON-запись 50000 строк
  3. Выполняется примерно за 1,5 секунды.
  4. Повторите процесс. На этот раз у него есть существующие данные, которые необходимо проанализировать для поиска дубликатов. Те же результаты. Менее 2 секунд
  5. Повторите шаг 4 N всегда с одинаковыми результатами.
  6. Запустить ALTER на SP без внесения ЛЮБЫХ изменений в сам SP
  7. Повторите шаг 4. На этот раз это займет 30-40 секунд !!!
  8. Удалить данные в таблице назначения, повторить все шаги, те же результаты.

Я читал о сниффинге параметров, пробовал такие вещи, как преобразование переданных параметров в локальные параметры и добавление WITH RECOMPILE, но пока все результаты одинаковы.

Если бы это произошло в Prod, это было бы неприемлемо. У кого-нибудь есть идеи?

Спасибо!

1 Ответ

4 голосов
/ 11 марта 2019

Это немного длинно для комментария.

SQL Server кэширует планы запросов в хранимой процедуре при их первом запуске.В вашем случае первый прогон имеет пустую таблицу, поэтому план запроса основан на пустой таблице.Кажется, это хороший план запроса для вашей проблемы.

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

По любой причине этот второй план запроса намного хуже первого.Я не знаю почему.Обычно проблема в другом (план запроса в пустой таблице хуже).

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

...