Уважаемый [ваше имя здесь]!
О нет, мне жаль это слышать! Давайте начнем с некоторых основ, которые помогут вам быстро освоиться.
То, с чем вы сталкиваетесь, называется параметризацией
Это выход из странной странной проблемы. Имя скатывается с языка. Как немецкое слово для белка.
И это обычно твой друг.
Когда запрос попадает на ваш сервер, план должен быть скомпилирован. Чтобы сэкономить время и ресурсы позже, план выполнения кэшируется на основе оценочных строк, которые этот параметр заставит ваш код обработать и вернуть.
Самый простой способ представить себе, как это происходит, - представить себе хранимую процедуру, которая должна считать вещи из двух однобоких групп.
Например:
Люди в футболках CrossFit, которые не пострадали: ноль
Люди в рубашках CrossFit, которые морщатся, когда морщатся: Все
Очевидно, что одно выполнение этого кода должно было бы выполнять гораздо больше работы, чем другое, и планы запросов, которые вы хотели бы выполнять совершенно по-другому, выглядели бы совершенно по-другому.
Что я против?
Это действительно трудная проблема для поиска, тестирования и исправления.
- Трудно найти, потому что это не происходит последовательно
- Это сложно проверить, потому что вам нужно знать, какие параметры вызывают разные планы
- Это трудно исправить, потому что иногда требуется настройка запросов и индексов
- Это трудно исправить, потому что вы не сможете изменить запросы или индексы
- Это трудно исправить, потому что даже если вы измените запросы или индексы, он все равно может вернуться
Быстрые исправления
Иногда все, что вам нужно, это немного ясности. Вернее, кеш вашего плана делает.
Если это хранимая процедура
Попробуйте запустить EXEC sys.sp_recompile @objname = N'schema.procname'
. Это заставит процедуру перекомпилировать новый план при следующем запуске.
Что это не исправит:
- Процессы, в настоящее время выполняющие это.
Что это не гарантирует:
- Следующий процесс, который запускается после перекомпиляции, будет использовать параметр, который даст вам хороший план.
Вы также можете указать sp_recompile
на таблицу или представление, но предупреждайте, что весь код, касающийся этой таблицы или представления, будет перекомпилирован. Это может сделать проблему намного сложнее.
Если это параметризованный запрос
Ваша работа немного сложнее. Вам нужно отследить дескриптор SQL. Вы не хотите освобождать весь кэш плана - так же, как при использовании sp_recompile
таблицы или представления, вы можете вызвать (ха-ха-ха) целую кучу непреднамеренных последствий.
Самый простой способ понять эту команду - запустить sp_BlitzWho *! Есть столбец с именем «Исправить сниффинг параметров», в котором есть команда для удаления одного плана из кэша. Это имеет те же недостатки, что и перекомпиляция.
Что это не исправит:
- Процессы, в настоящее время выполняющие это.
Что это не гарантирует:
- Следующий процесс, который запускается после перекомпиляции, будет использовать параметр, который даст вам хороший план.
Мне все еще нужна помощь!
Нам понадобятся следующие вещи:
- Хороший план запроса, если это возможно
- Плохой план запроса
- Используемые параметры
- Вопрос в вопросе
- Определения таблиц и индексов
Получение планов запроса и запроса
Если запрос выполняется, вы можете использовать sp_BlitzWho * или sp_WhoIsActive для захвата выполняющихся в данный момент запросов.
EXEC sp_BlitzWho;
EXEC sp_WhoIsActive @get_plans = 1;
Если запрос в настоящий момент не выполняется, вы можете проверить его в кэше плана, используя 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';
Вы должны увидеть довольно похожий вывод из любого из них. Опять же, план запроса, приглашающий колонку с классным синим кликом, - ваш друг.
Самый простой способ поделиться планами - использовать Paste The Plan * или выгрузить XML в pastebin. Чтобы получить это, нажмите на один из тех, кто приглашает синие щелкающие столбцы. Ваш план запроса должен появиться на новой вкладке SSMS.
Если вам не терпится поделиться кодом и запросом своей компании, вы можете воспользоваться бесплатным инструментом Sentry One Plan Explorer для анонимизации вашего плана. Имейте в виду, что это усложняет получение помощи - анонимный код намного сложнее для чтения и понимания.
Все эти инструменты, о которых мы говорили, должны возвращать текст запроса. Вам не нужно больше ничего делать здесь.
Получить параметр (ы) немного сложнее. Если вы используете Plan Explorer , внизу есть вкладка, в которой перечислены все из них для вас.
Если вы используете sp_BlitzCache *, есть кликабельный столбец, который дает вам оператор выполнения для хранимых процедур.
Получение таблицы и определения индекса
Вы можете легко щелкнуть правой кнопкой мыши в SSMS, чтобы написать сценарий.
Если вы хотите получить все в одном кадре, sp_BlitzIndex * может помочь, если вы направите его прямо на стол.
EXEC dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow2010',
@SchemaName = 'dbo',
@TableName = 'Users';
Это даст вам определение таблицы (хотя и не как оператора create) и создаст операторы для всех ваших индексов.
Сбор и добавление этой информации к вашему вопросу должно дать людям достаточно информации, чтобы помочь или направить вас в правильном направлении.
Я хочу сделать это сам!
Ну круто Я рад за тебя. Вы сумасшедший человек.
Есть много способов, которыми люди думают, что они "исправляют" сниффинг параметров:
Но они действительно просто отключают анализ параметров по-разному. Это не значит, что они не могут решить проблему, они просто не могут понять причину.
Это потому, что найти причину обычно довольно сложно. Вы должны искать эти противные "проблемы качества плана".
Начиная с быстрых против медленных планов, ищите различия как:
- Используемые индексы
- Присоединиться к заказу
- Серийный против параллельного
Также обратите внимание на различные операторы, которые делают ваш код чувствительным к анализу параметров:
- Lookups
- Сорта
- Тип соединения
- Предоставление памяти (и, соответственно, разливов)
- Катушки
Не зацикливайтесь на поиске или сканировании, фрагментации индекса или любых других вещах, связанных с культом, которые люди обдумывают и обсуждают.
Обычно существует довольно простая проблема с индексацией. Иногда код нуждается в небольшом переписывании.
Если вы хотите узнать больше о сниффинге параметров:
Если вы читаете это, и вы думаете, что я пропустил ссылку или полезный инструмент, оставьте комментарий. Я сделаю все возможное, чтобы держать это в курсе.