Чому запит раптово повільніше, ніж це було вчора?


76

[Вітання]

(перевірте одну)

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

У мене є (позначте все, що стосується)

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

це було нормально (якщо застосовується)

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

але зараз раптом повільніше.

Я вже перевірив, чи не заблокований він, і чи не є жертвою якогось довгого виконання завдань з технічного обслуговування, звіту чи іншого виходу з діапазону.

У чому проблема, що мені робити та яку інформацію я можу надати, щоб отримати допомогу?

[*Insert appropriate closing remarks*]

Відповіді:


88

Шановний [твоє ім’я тут]!

О ні, мені шкода це чути! Почнемо з декількох основ, щоб ви зафіксувались на мить.

Те, з чим ви стикаєтесь, називається Parameter Sniffing

Це вихід з дивовижною проблемою віггі. Назва перекочується прямо з язика. Як німецьке слово для білки.

І це, як правило, твій друг.

Коли запит потрапляє на ваш сервер, план повинен бути складений. Щоб згодом заощадити час та ресурси, план виконання кешується на основі оціночних рядків, параметр яких призведе до обробки та повернення коду.

Найпростіший спосіб уявити це погано - це уявити збережену процедуру, яка потребує підрахунку речей з двох груп, що перебувають у розрізі.

Наприклад:

  • Люди, які носять футболки 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+ та увімкнено магазин запитів, ви можете використовувати 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 у пастину. Для цього натисніть будь-який із тих, хто запрошує сині кліки колонки. План запитів повинен з’явитися на новій вкладці SSMS.

Горіхи

Якщо вам не подобається ділитися кодом і запитом вашої компанії, ви можете скористатися безкоштовним інструментом програми Explorer Sentry One для анонімності вашого плану. Майте на увазі, це ускладнює отримання довідки - анонімований код набагато складніше читати та розбирати.

Усі ці інструменти, про які ми говорили, повинні повертати текст запиту. Тут вам більше нічого не потрібно робити.

Отримати параметри (и) трохи складніше. Якщо ви використовуєте План Провідник , внизу є вкладка, у якій перераховано їх усі.

Горіхи

Якщо ви використовуєте sp_BlitzCache *, є стовпчик, що можна натискати, який дає вам заяву про виконання збережених процедур.

Горіхи

Отримання визначень таблиці та індексу

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

Горіхи

Якщо ви хочете отримати все за один кадр, sp_BlitzIndex * може допомогти, якщо навести його прямо на стіл.

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

Це дасть вам визначення таблиці (хоча не як оператор створення) та створить оператори для всіх ваших індексів.

Збираючи та додаючи цю інформацію до свого запитання, люди повинні отримати достатньо інформації, щоб допомогти або направити вас у правильному напрямку.

Я хочу зробити це сам!

Ну, круто. Я радий за вас. Ти божевільна людина.

Є багато способів, на які люди думають, що вони "виправляють" нюхання параметрів:

Але вони справді відключають нюхання параметрів різними способами. Це не означає, що вони не можуть вирішити проблему, вони просто не дійсно до першопричини.

Це тому, що потрапити до першопричини, як правило, важко. Ви повинні шукати ті прискіпливі "питання якості" плану.

Починаючи з планів швидких проти повільних, шукайте відмінності на зразок:

  • Використовувані індекси
  • Приєднуйтесь до замовлення
  • Серіал проти паралелі

Також шукайте різних операторів, які роблять ваш код чутливим до нюху параметрів:

  • Пошук
  • Сорти
  • Тип приєднання
  • Надані пам’яті (і за розширенням, розливи)
  • Шпулі

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

Зазвичай існує досить основна проблема індексації. Іноді код потрібно трохи переписати.

Якщо ви хочете дізнатися більше про нюхання параметрів:

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



28

Нюхання параметрів - не єдина можлива причина для різної продуктивності запиту. Будь-яка з перерахованих нижче причин може проявляти однакові симптоми:

  1. Розподіл / обсяг даних змінено, перетинаючи перехідну точку рішення щодо оптимізатора пошуку
  2. Індекси / файли роздроблені
  3. Статистика була оновлена ​​/ додана / знижена або стала несвіжою та оманливою через зміни даних
  4. Змінено використання пам'яті Windows
  5. Журнали транзакцій заповнені і не обрізаються, що призводить до повторного розширення фізичного файлу
  6. Змінено схему - додано, змінено або відмінено показник / індексований вигляд / стовпець / обмеження, тип даних змінено тощо.
  7. Налаштування трасування прапора змінено
  8. Застосовано оновлення Windows
  9. База даних або налаштування сервера змінено
  10. Змінено рівень серверного КС
  11. Налаштування сеансу клієнтської програми змінені

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


1
Дякуємо за редакцію Павла. @sp_BlitzErik - Мені не було наміру надавати поради щодо конкретних тем, а лише підвищити обізнаність про їх існування, і, можливо, варто перевірити їх. Це жодним чином не означає зменшення вашої великої посади. Ви розбиралися з нюханням параметрів поглиблено, професійно та з гарним гумором. Мені подобалось читати це. Я хочу лише переконатися, що якщо хтось тут завітає на цю посаду, слідуючи захоплюючому заголовку, він ознайомиться з альтернативними потенційними причинами. IMHO це додає значення вашій посаді, але якщо ви все ще хочете, щоб я її видалив, дайте мені знати.
SQLRaptor

Ні, зовсім ні. Я ніколи не просив когось видалити відповідь, яка не є неправильною чи шкідливою. Я все ще думаю, що ви могли б додати трохи деталей, але це врешті залежить від вас.
Ерік Дарлінг

10

Просто додайте до існуючих відповідей у ​​випадку, якщо вони не допомогли, коли "раптом" ваші запити поводяться по-різному на наступний день, перевірте:

  • Чи змінилася схема використаних таблиць з останнього разу? У випадку SSMS ви можете клацнути правою кнопкою миші сервер у Провіднику об'єктів і вибрати Reports → Standard Reports → Schema Changes History.
  • Чи різко зросла кількість предметів? Можливо, ваш запит просто набагато повільніше, коли в використаних таблицях є багато даних.
  • Хтось інший використовує базу даних одночасно з вами? Можливо, виберіть проміжки часу, де ви не заважаєте працювати один одному.
  • Як виглядає системна статистика? Можливо, сервер працює в режимі гарячого і перебуває в режимі перезавантаження процесора, або на жорстких дисках не вистачає місця або поміняється місцями. Можливо, є інша технічна проблема, як-от пожежа чи повінь у серверній кімнаті.

7

Інша можливість полягає в тому, що ваша команда інфраструктури використовує такі інструменти, як vMotion на VMware, а VM, що підтримує ваш екземпляр SQL, безперебійно переміщується з хоста в хост, не знаючи про це DBA.

Це справжня проблема, коли ваша інфраструктура є позачерговою ... У мене справжній кошмар.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.