Код створює інший план, коли виконується ad-hoc vs. у збереженій процедурі


9

У мене є операція видалення, яка використовує поганий план при запуску всередині збереженої процедури, але вибирає набагато кращий план при запуску ad-hoc.

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

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

ОНОВЛЕННЯ: Я думаю, що це, мабуть, були параметри зрештою - коли я запускав спеціальний код зі змінною жорсткого коду, я можу отримати "поганий" план з потрібним значенням (це дата, значення, які мають рік здається, генерують "добрий" план). Тепер про спробу примусити «добрий» план щодо процесора за допомогою підказки на запит.

РІШЕННЯ: Я в кінцевому підсумку отримав потрібний план, використовуючи підказку ОПТИМІЗУВАННЯ ДЛЯ НЕЗАЄМОГО


Це, мабуть, нюхає параметр . Чи посилається на запит змінної у своєму WHEREпункті?
Нік Чаммас

4
Чи можете ви додати код, будь ласка
gbn

Також розмістіть плани десь, будь ласка. Оскільки це буде досить важко сказати, чому саме плани відрізняються.
Аарон Бертран

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

План спеціального коду (хороший) виконує сканування таблиці невеликої таблиці (у якої лише 5-10 рядків) і використовує некластеризований індекс великої таблиці, щоб знайти, які рядки потрібно перевірити в ПК великого столу. Я спробую здійснити реальні плани, як тільки зможу.
msgisme

Відповіді:


5

Звичайні підозрювані:

  1. константи в adhoc, параметри в коді
  2. невідповідність типів даних у коді
  3. нюхання параметра

Точка 1: оптимізатор може вибрати найкращий план для констант.
Змінити константи = змінити план. Параметризований плеєр можна налаштувати

Точка 2 запровадить неявні перетворення через перевагу типу даних,
наприклад, колонка varchar порівняно з параметром nvarchar

Точка 3: використовувати маскування параметрів або OPTIMIZE FOR NEKNOWN
Edit: Щоб перевірити: запустити збережений proc, запустити sp_updatestats, запустити ще раз. Це призведе до недійсності кешованих планів, що краще, ніж очищення кешу плану

Редагувати: після коментаря jcolebrand

Ви можете відключити нюхання кількома способами. Основні 3 є

  • РЕКОМПЛІЯ. Це дурне ІМО.
  • ОПТИМІЗУЙ (sic) ДЛЯ НЕЗНАЧЕНОГО
  • Маскування параметрів

Маскування параметрів:

DECLARE @MaskedParam varchar(10)
SELECT @MaskedParam = @SignaureParam

SELECT...WHERE column = @MaskedParam

Маскування та підказка OPTIMIZE мають однаковий ефект (можливо, з різних причин). Тобто оптимізатору доводиться використовувати статистику та розподіл даних ( Примітка: все ще під тестуванням Марк Сторі-Сміт ) оцінювати параметри за власними достоїнствами ? , а не те, що вони були в останній дзвінок. Оптимізатор може перекомпілювати чи ні. SQL Server 2005 додав рекомпіляцію рівня висловлювань, щоб було менше впливу

Тепер, чому план з параметрами "нюхали" є "липким" порівняно з маскованими / "невідомими" параметрами, я не впевнений.

Я використовував маскування параметрів з SQL Server 2000 для всіх, крім найпростішого коду. Я зазначив, що це може статися зі складнішим кодом. І на моїй старій роботі у мене є кілька проектів звітів, які я можу змінити параметри плану за замовчуванням. Я вважаю, що підхід "культового вантажу" був простішим, ніж заклик підтримки.

Редагувати 2, 12 жовтня 2011 року, після деякого чату

  • Маскування параметрів та ОПТИМІЗУВАННЯ ДЛЯ НЕЗАЄМОГО мають такий самий ефект, наскільки я можу сказати
    Підказка чистіша, ніж маскування, але додана до SQL Server 2008.

  • Нюхання параметрів відбувається під час компіляції.
    З допомогою RECOMPILE створює новий план кожного виконання. Це означає, що поганий вибір за замовчуванням вплине на план. На своєму останньому завданні я міг це легко продемонструвати за допомогою деякого коду звіту: зміна значень за замовчуванням змінила план незалежно від наданих параметрів.

  • Ця стаття MS Connect цікава: Субоптимальне використання індексу в збереженій процедурі (згадане в одному з відповідей на відповідь нижче)

  • Про це згадує і Боб Бошемін

Невирішені питання

  • Чи все-таки нюхання все ще застосовується за допомогою RECOMPILE? Тобто, якщо оптимізатор знає відкинути план, він спрямований на повторне використання?

  • Чому обнюхані плани "липкі"?

Посилання від SO:


1. Параметр у sp є змінною в коді 2. Знову ж, тип даних 3. Я запустив обидва з великою різноманітністю параметрів, і я отримую той самий план щоразу. Я очищав кеш після кожної спроби.
msgisme

1
Re: пункт 3. Ви також можете запустити операцію з OPTION (RECOMPILE)або всім процесом, WITH RECOMPILEщоб змусити SQL Server ігнорувати існуючі плани.
Nick Chammas

3
До речі OPTIMIZE, адже Microsoft - американська компанія. :)
Нік Чаммас

1
@Gbn якісь думки щодо запобігання / поразки нюху параметрів?
jcolebrand

1
@jcolebrand: проста відповідь - "ні" :-)
gbn

2

Не забувайте, що налаштування ANSI, які ви встановили для плану з'єднання, роль у виборі плану виконання. Коли програма викликає збережену процедуру, вона, ймовірно, має інші настройки ANSI, ніж ваше з'єднання SSMS.

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