Почему мой запрос вдруг медленнее, чем вчера?

[Приветствия]

(отметьте один)

[ ] Well trained professional, [ ] Casual reader, [ ] Hapless wanderer,

У меня есть (отметьте все, что применимо)

[ ] query [ ] stored procedure [ ] database thing maybe  

, который работал нормально (если применимо)

[ ] yesterday [ ] in recent memory [ ] at some point 

, но теперь он становится медленнее.

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

В чем проблема, что мне делать, и какую информацию я могу предоставить, чтобы получить некоторую помощь?

[*Insert appropriate closing remarks*]
60 голосов | спросил sp_BlitzErik 20 PMpFri, 20 Apr 2018 23:10:14 +030010Friday 2018, 23:10:14

4 ответа


75

Дорогой [твое имя здесь]!

О нет, мне жаль это слышать! Начнем с некоторых основополагающих принципов, чтобы вы были исправлены в jiffy.

То, что вы запускаете, называется параметром Sniffing

Это пугающая странная проблема. Название перекатывается прямо с языка. Как немецкое слово для белки.

И это обычно ваш друг.

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

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

Например:

  • Люди, носящие рубашки CrossFit, которые не получили травмы: Zero

  • Люди, носящие рубашки CrossFit, которые вздрагивают, когда они вздрагивают: Все

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

Что я против?

Это действительно сложная проблема для поиска, тестирования и исправления.

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

Быстрые исправления

Иногда все, что вам нужно, - это немного ясности. Вернее, ваш кэш плана делает.

Если это хранимая процедура

Попробуйте запустить EXEC sys.sp_recompile @objname = N'schema.procname'. Это заставит процедуру перекомпилировать новый план при следующем запуске.

Что это не будет исправлено:

  • Процессы, выполняемые в настоящий момент.

Что это не гарантирует:

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

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

Если это параметризованный запрос

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

Самый простой способ понять эту команду - запустить sp_BlitzWho *! Существует столбец под названием «исправление параметров sniffing», в котором есть команда удалить один план из кеша. Тем не менее, это имеет те же недостатки, что и перекомпиляция.

Что это не будет исправлено:

  • Процессы, выполняемые в настоящий момент.

Что это не гарантирует:

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

Мне все еще нужна помощь!

Нам понадобятся следующие вещи:

  • Хороший план запроса, если возможно
  • Плохой план запроса
  • Используемые параметры
  • Запрос, о котором идет речь
  • Обозначения таблиц и индексов

Получение планов запросов и запросов

Если запрос запущен, вы можете использовать sp_BlitzWho * или sp_WhoIsActive для захвата выполняемых в настоящее время запросов.

EXEC sp_BlitzWho;

EXEC sp_WhoIsActive @get_plans = 1;

 NUTS

Если запрос в настоящее время не выполняется, вы можете проверить его в кеше плана, используя sp_BlitzCache *.

Если вы используете SQL Server 2016+ и включили Query Store, вы можете использовать sp_BlitzQueryStore *.

EXEC dbo.sp_BlitzCache @StoredProcName = 'Your Mom';

EXEC dbo.sp_BlitzQueryStore @StoredProcName = 'Your Mom';

Это поможет вам отслеживать кешированную версию (ы) вашей хранимой процедуры. Если это просто параметризованный код, ваш поиск немного сложнее. Это может помочь, однако:

EXEC dbo.sp_BlitzCache @QueryFilter = 'statement';

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

 NUTS

Самый простой способ поделиться планами - использовать Вставить план * или сбросить XML в pastebin. Чтобы получить это, нажмите на один из тех приглашающих синих кликов. Ваш план запроса должен появиться на новой вкладке SSMS.

 NUTS

Если вам сложно разобраться с кодом и запросом вашей компании, вы можете использовать бесплатный инструмент Plan Explorer от Sentry One , чтобы анонимизировать ваш план. Имейте в виду, что это затрудняет получение помощи - анонимный код намного труднее прочитать и выяснить.

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

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

 NUTS

Если вы используете sp_BlitzCache *, есть кликабельный столбец, который дает вам инструкцию выполнения хранимых процедур.

 NUTS

Получение описаний таблиц и индексов

Вы можете легко щелкнуть правой кнопкой мыши в SSMS, чтобы выполнить сценарий.

 NUTS

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

EXEC dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow2010',
                       @SchemaName = 'dbo',
                       @TableName = 'Users';

Это даст вам определение таблицы (хотя и не как оператор создания), и создаст инструкции для всех ваших индексов.

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

Я хочу сделать это сам!

Ну, круто. Я рад за тебя. Вы сумасшедший человек.

Есть много способов, по которым люди думают, что они «исправляют» параметр sniffing:

Но это действительно просто отключает параметр sniffing по-разному. Это не значит, что они не могут решить проблему, они просто не понимают основную причину.

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

Начиная с быстрых и медленных планов, найдите различия, например:

  • Используемые индексы
  • Порядок сортировки
  • Serial vs Parallel

Ищите разные операторы, которые делают ваш код чувствительным к параметру sniffing:

  • Lookups
  • Сорта
  • Тип соединения
  • Память выделяет (и, как следствие, разливы)
  • Катушки

Не слишком обернуты в поиске и сканировании, фрагментации индекса или каких-либо предметов, которые люди подойдут и о чем беспокоятся.

Обычно существует довольно простая проблема с индексацией. Иногда код нуждается в небольшом переписывании.

Если вы хотите узнать больше о sniffing параметров:

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


* Полное раскрытие, я вношу свой вклад в эти скрипты с открытым исходным кодом. Они лицензированы MIT и все эти хорошие вещи, поэтому вам не нужно беспокоиться о том, что вы с ними делаете.

ответил sp_BlitzErik 20 PMpFri, 20 Apr 2018 23:10:14 +030010Friday 2018, 23:10:14
24

Параметр sniffing не является единственной возможной причиной изменения производительности запроса. Любая из следующих распространенных причин может показать те же симптомы:

  1. Изменено распределение /объем данных, пересекающий точку опроса дерева поиска оптимизатора.
  2. Индексы /файлы получили фрагментацию
  3. Статистика была обновлена ​​/добавлена ​​/удалена или устарела и введена в заблуждение из-за изменений данных.
  4. Использование памяти Windows изменилось
  5. Журналы транзакций заполнены и не усекаются, что приводит к повторному расширению физического файла.
  6. Изменена схема - добавлен, изменен или удален индекс /индексированный вид /столбец /ограничение, изменен тип данных и т. д.
  7. Изменены настройки флага трассировки
  8. Было применено обновление Windows
  9. Изменена настройка базы данных или сервера.
  10. Изменен уровень сервера CU
  11. Изменены настройки сеанса клиентского приложения.

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

ответил SQLRaptor 21 AMpSat, 21 Apr 2018 03:15:51 +030015Saturday 2018, 03:15:51
9

Просто добавьте к существующим ответам, если они не помогли, когда «неожиданно» ваши запросы ведут себя по-другому на следующий день, проверьте:

  • Сработала ли схема для использованных таблиц с последнего раза? В случае SSMS вы можете щелкнуть правой кнопкой мыши по серверу в Проводнике объектов и выбрать Reports → Standard Reports → Schema Changes History.
  • Значительно увеличилось количество предметов? Возможно, ваш запрос намного медленнее, когда в используемых таблицах много данных.
  • Кто-нибудь другой использует базу данных одновременно с вами? Возможно, выберите временные интервалы, где вы не будете мешать работе друг друга.
  • Как выглядит статистика системы? Возможно, сервер работает горячим и дросселирует процессор, или на жестких дисках заканчивается место или своп. Возможно, есть еще одна проблема с оборудованием, например, пожар или наводнение в серверной комнате.
ответил user1306322 21 PMpSat, 21 Apr 2018 14:23:18 +030023Saturday 2018, 14:23:18
0

Другая возможность заключается в том, что ваша команда инфраструктуры использует такие инструменты, как vMotion для VMware, а виртуальная машина, поддерживающая ваш экземпляр SQL, легко перемещается от Host to Host без знания DBA.

Это настоящая проблема, когда ваша инфраструктура не работает ... У меня настоящий кошмар с ней.

ответил pacreely 5 J0000006Europe/Moscow 2018, 14:11:52

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132