Як я можу видалити поганий план виконання з бази даних Azure SQL?


12

DBCC FREEPROCCACHEне працює в Azure SQL DB. Як інакше я можу змусити план вигнати себе з кешу таким чином, щоб це не зашкодило виробничій системі (тобто я не можу просто перейти настільно змінювати таблиці невільно)? Це спеціально для SQL, створеного Entity Framework, тому це не самокеровані збережені програми - це ефективно динамічний SQL.

(Джерело було поганим індексом -> погана статистика тощо. Це все виправлено, але поганий план не піде.)

ОНОВЛЕННЯ: Я вибрав рішення @ mrdenny, коли він першим потрапив туди. Однак я успішно використовую сценарій @Aaron Bertrand для виконання твору. Дякую всім за допомогу !!


Чи можете ви виконати sp_recompile в Azure?
мрденний

Так. Що саме я би запускав? У нас немає збережених програм. Це динамічний SQL sp_executesql.
Jaxidian

2
Ви можете самостійно запустити його на стіл, і це має розмити плани, які використовують цю таблицю. (Якщо це спрацює, я зроблю це відповіддю.)
mrdenny

1
Я просто спробував це на столі, і він, очевидно, блокує таблицю в транзакції під час обробки. Я спробував це на 10-стовпчиковій таблиці з лише 24 записами, а на закінчення пішло більше хвилини. За цей час мені не вдалося запитати таблицю. Я не можу запустити щось подібне на наших реальних столах у виробництві!
Jaxidian

1
Чорт, це облом. Схоже, вам потрібно буде змінити схему, як-от додати нульовий стовпець, а потім скинути його. Це також видалить кеш, і це повинно бути швидко. Тестування покаже точно.
mrdenny

Відповіді:


12

Тепер Azure SQL безпосередньо підтримує це

База даних SQL Azure безпосередньо підтримує очищення кеш-файлів поточної бази даних без будь-яких злому:

ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

Додаткова інформація

Наступний сценарій ( Шеннон Гоуен ) може бути використаний для перегляду процесу крок за кроком:

-- run this script against a user database, not master
-- count number of plans currently in cache
select count(*) from sys.dm_exec_cached_plans;

-- Executing this statement will clear the procedure cache in the current database, which means that all queries will have to recompile.
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

-- count number of plans in cache now, after they were cleared from cache
select count(*) from sys.dm_exec_cached_plans;

-- list available plans
select * from sys.dm_exec_cached_plans;

Я ще цього не пробував, але якщо це насправді функціонально, то це, мабуть, "найкраща" відповідь станом на початок 2017 року. :-)
Jaxidian

Я спробував це (на Преміум БД), і це спрацювало.
Ремі Лемаршанд

Я позначив це як оновлений "Прийнятий відповідь", але сам ще цього не перевіряв. Я базую це безпосередньо на відгуках Тодда та Ремі. Дякую усім!
Jaxidian

Щойно переглянувши, я використав це, і це добре спрацювало для мене! Я додаю тут кілька додаткових сценаріїв до відповіді Тодда, щоб збагатити його, але його посада вдарила нігтем по голові.
Jaxidian

Здається, це не працює для мене - воно просто виконується, але списки все ще повно - я на SQL Azure - що може бути не так?
Дірк Бур

12

Сьогодні немає явного способу зробити це, але це не постійний сценарій (команда DBCC все ще не підтримується, але читається в магазині запитів ). Навіть коли звернення до зміни схеми є прийнятним, воно може бути не тим, що ви хочете, оскільки це призведе до недійсності всіх планів, пов’язаних із базовим об'єктом, а не лише поганого.

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

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER TABLE '
  + QUOTENAME(SCHEMA_NAME([schema_id])) 
  + '.' + QUOTENAME(name) + ' ADD fake_column INT NULL;
  ALTER TABLE ' 
  + QUOTENAME(SCHEMA_NAME([schema_id]))
  + '.' + QUOTENAME(name) + ' DROP COLUMN fake_column;'
FROM sys.tables
--WHERE name IN, LIKE, etc.

PRINT @sql;

-- if the command > 8K, you can see the second chunk e.g.

PRINT SUBSTRING(@sql, 8001, 8000);

--EXEC sys.sp_executesql @sql;

(Я написав підказку щодо цієї "тривалості динамічного SQL" ...)


У моєму випадку видаляти їх все набагато краще, ніж залишати там поганих. Дякую за голову вгору Я знаю, що ви не можете сказати мені функції, але чи можете ви сказати мені, коли ви більше не можете обмежуватись тим, про що не можете говорити? ;-)
Jaxidian

Це також засекречено, вибачте. :-)
Аарон Бертран

Не впевнений, що ви маєте на увазі під посиланням. Я мав на увазі те, що ваша nvarchar(max)змінна досягає межі після 4000 знаків, 8000 символів, якщо я її зміню varchar(max). Запуск цього точного сценарію. У нас ~ 450 таблиць, тому ми легко потрапили (~ 30/60 таблиць у). varchar(max)дійсний синтаксис, він просто ідентичний varchar(8000)і nvarchar(max)ідентичний nvarchar(4000).
Jaxidian

3
Ну так, коли ви PRINTкомандуєте, вона показує лише 8000 байт. Це обмеження PRINTкоманди, а не Azure. Якщо ви запустите команду, вона буде працювати, навіть якщо ви не зможете візуально перевірити всю справу.
Аарон Бертран

... да, вибач, я думаю, ти маєш рацію! Дякуємо, що виправили мене! Ось що відбувається, коли ваша дружина очікувала, що ви підете 25 хвилин тому ... ;-) Цей сценарій ідеально працює для мене!
Jaxidian

6

Додайте до таблиці нульовий стовпчик, а потім скиньте його. Це змусить SQL очистити кеш для цього об'єкта.

Що стосується виконання всіх таблиць, курсор повинен виконати трюк. Просто використовуйте ім’я стовпця, яке ніколи не буде в жодній таблиці, як-от "zzzzzz_go_away" або щось подібне.


4

База даних SQL Azure в даний час не підтримує DBCC FREEPROCCACHE, тому ви не можете вручну видалити план виконання з кешу. Однак якщо ви внесете зміни в таблицю або перегляд, на який посилається запит ( ALTER TABLE/ ALTER VIEW), план буде видалений з кешу. ( Довідка .)


Я вже знав усе, що ви тут розмістили. Це ні збережена процедура, ні перегляд, тому я не можу змінити жодну з них. Як я міг змінити свої таблиці незначним чином, перебуваючи під навантаженням і не викликаючи простоїв або блокування таблиці, щоб це спровокувати?
Jaxidian

1
Можна, можливо, додати фіктивний стовпець, а потім скинути його. Це видалить план з кешу. Наскільки великий стіл?
Кін Шах

Зрештою, це рішення, як рекомендує @mrdenny. Дякую за допомогу!! :-)
Jaxidian

1
Дякую ... Лише кілька секунд не вистачило часу. Відповідав на інший пост у stackexchange ...
Кін Шах

1

Щоб очистити весь план виконання, використовуйте це:

    SET NOCOUNT ON

DECLARE @lcl_name VARCHAR(100)
DECLARE @addcolumnSql nVARCHAR(MAX)
DECLARE @dropcolumnSql nVARCHAR(MAX)

DECLARE cur_name CURSOR FOR
SELECT name
FROM sysobjects
WHERE type = 'U'
OPEN cur_name
FETCH NEXT FROM cur_name INTO @lcl_name
WHILE @@Fetch_status = 0
BEGIN
set @addcolumnSql = 'alter table [' + @lcl_name + '] add temp_col_to_clear_exec_plan bit'
EXEcute sp_executesql @addcolumnSql
print @addcolumnSql
set @dropcolumnSql = 'alter table [' + @lcl_name + '] drop column temp_col_to_clear_exec_plan'
EXEcute sp_executesql @dropcolumnSql
print @dropcolumnSql
--  EXEC (@lcl_name )
FETCH NEXT FROM cur_name INTO @lcl_name
END
CLOSE cur_name
DEALLOCATE cur_name
SET NOCOUNT OFF

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

Трохи більше пояснено тут http://christianarg.wordpress.com/2013/08/22/remove-execution-plans-from-the-procedure-cache-in-sql-azure/

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