ЗАКАЗ ОПЦІЙНОЇ СИЛИ покращує продуктивність, поки рядки не будуть видалені


9

У мене є дещо складний запит SQL Server 2008 (близько 200 рядків досить щільного SQL), який не працював так, як мені потрібно. З часом продуктивність знизилася з приблизно .5 до приблизно 2 секунд.

Поглянувши на план виконання, було досить очевидно, що, переупорядкувавши з'єднання, можна підвищити ефективність роботи. Я так і зробив ... аж до .3 секунди. Тепер запит має підказку "ЗАМОВЛЕННЯ ВАРІТТЯ СИЛИ" , і життя - це добре.

Сьогодні приходить мене, прибираючи базу даних. Я архівувати близько 20% рядків, не беручи ніяких дій у відповідній базі даних , за винятком видалення рядків ... план виконання отримує ПОВНІСТЮ обливали . Він повністю неправильно оцінює, скільки рядків повернеться певних підрядків, і (наприклад) замінює:

<Hash>

з

<NestedLoops Optimized='false' WithUnorderedPrefetch='true'>

Зараз час запиту зменшується приблизно від .3 до приблизно 18-х. (!) Просто тому, що я видалив рядки. Якщо я видаляю підказку запиту, я повернусь до часу запиту приблизно 2 секунди. Краще, але гірше.

Я відтворив проблему після відновлення бази даних на декількох місцях і серверах. Просто видалення приблизно 20% рядків з кожної таблиці завжди викликає цю проблему.

  1. Чи нормально це для порядку примусового приєднання, щоб зробити оцінки запиту абсолютно неточними (і, таким чином, час запитів непередбачуваним)?
  2. Чи варто просто очікувати, що мені доведеться або приймати недооптимальну ефективність запиту, або дивитися на нього як на яструба і часто вручну редагувати підказки запитів? Чи, можливо, натякають і на кожне приєднання? .3s до 2s - великий удар.
  3. Чи очевидно, чому оптимізатор підірвався після видалення рядків? Наприклад, "так, було проведено вибіркове сканування, і тому, що я архівував більшість рядків раніше в історії даних, зразок давав розріджені результати, тож він недооцінював потребу в відсортованій хеш-операції"?

Якщо ви хочете побачити плани виконання, запропонуйте, де я можу розмістити їх. Інакше я пробував найдивовижніший шматочок. Ось основна помилкова оцінка, числа в паренах складають (оціночні: фактичні) рядки.

                             /  Clustered Index Scan (908:7229)
Nested Loops (Inner Join) --<
                             \  NonClustered Index Seek (1:7229)

Зверніть увагу, що внутрішній цикл повинен сканувати 908 рядків, але замість цього сканує 52 258 441. Якби це було точно, ця гілка пробігла б приблизно 2 мс, а не 12 сек. Перед видаленням рядків ця внутрішня оцінка приєднання була виключена лише загальним коефіцієнтом 2 і виконувалася як хеш-відповідність на двох кластерних індексах.

Відповіді:


6

Чи нормально це для порядку примусового приєднання, щоб зробити оцінки запиту абсолютно неточними (і, таким чином, час запитів непередбачуваним)?

Використання FORCE ORDER не робить оцінки недостовірними, видалення рядків не було. Примусове оновлення статистичних даних у таблиці може підвищити точність оцінки.

Чи варто просто очікувати, що мені доведеться або приймати недооптимальну ефективність запиту, або дивитися на нього як на яструба і часто вручну редагувати підказки запитів? Чи, можливо, натякають і на кожне приєднання? .3s до 2s - великий удар.

Переважно було б забезпечити, щоб оптимізатору було надано інформацію, необхідну для створення найкращого плану, без використання підказки FORCE ORDER. Роблячи це, він повинен краще впоратися зі змінами в базовому розподілі даних, не вимагаючи вручну втручання. При цьому, якщо характер даних такий, що кардинальність може суттєво змінюватися по годинах або день у годину, розглянемо використання керівництва плану, щоб забезпечити фіксацію плану.

Чи очевидно, чому оптимізатор підірвався після видалення рядків? Наприклад, "так, було проведено вибіркове сканування, і тому, що я архівував більшість рядків раніше в історії даних, зразок давав розріджені результати, тож він недооцінював потребу в відсортованій хеш-операції"?

Ви не згадали про кількість рядків у таблицях проблем, але ймовірно, що видалення також:

  • не видалили достатньо рядків, щоб запустити оновлення статистики. Це має відбутися, коли 20% рядків були змінені, але є можливість використовувати прапор трассингу 2371 для включення динамічного порогу.
  • ініціювало оновлення статистики, але зібрана вибірка не була репрезентативною. Виправте це, запустивши оновлення вручну з FULLSCAN .

Ви також можете зіткнутися зі старомодними проблемами нюху параметрів , для яких існує безліч варіантів. З RECOMPILE може бути дорогим варіантом вказати запит такого великого розміру, але його варто вивчити як на рівні процедури, так і на рівні заяви.


Просто уточнення, це, мабуть, семантика: "Використання FORCE ORDER не робить оцінки неточними, видалення рядків робило". Отже, ви вважаєте, що випадковий випадок "ЗАМОВЛЕННЯ СИЛИ" настільки покращив запит? Підказка не обмежила оптимізатора покладатися на статистику, вона швидше поставила б менше уваги або не була виявлена ​​в тесті додатків, оскільки ця менш достовірна статистика рідко була ключовою?
Шеннон

Я думаю, що так, оскільки оптимізатори віддавали перевагу вибору плану, щоб впоратися з неточними статистичними даними, але план, отриманий в результаті примусового приєднання, не робить. Мені не відомо, що ЗАМОВЛЕННЯ СИЛИ викликає будь-які зміни в оцінці статистики, хтось інший задзвенить, якщо знає щось протилежне. Також потрібно врахувати, чи відповідає значення, яке ви обрали для OPTIMIZE FOR. Можливо, статистика абсолютно гарна, але ви змушуєте план базуватися на значенні, яке не є репрезентативним.
Марк Сторі-Сміт

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