Як видалити конкретний невдалий план із кешу запитів SQL Server?


33

У нас є один конкретний запит SQL Server 2008 (не збережений протокол, але той самий рядок SQL - виконується кожні 5 хвилин), який з перервами кешує дуже поганий план запитів.

Цей запит, як правило, працює за кілька мілісекунд, але для цього поганого плану запитів потрібно 30+ секунд.

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


Відповіді:


39

Я зрозумів кілька речей

select * from sys.dm_exec_query_stats

покаже всі плани кешованих запитів. На жаль, там не відображено жодного тексту SQL.

Однак ви можете приєднати текст SQL до таких планів:

select plan_handle, creation_time, last_execution_time, execution_count, qt.text
FROM 
   sys.dm_exec_query_stats qs
   CROSS APPLY sys.dm_exec_sql_text (qs.[sql_handle]) AS qt

Звідси досить тривіально додати WHEREпункт про пошук SQL, який я знаю, у запиті, і тоді я можу виконати:

DBCC FREEPROCCACHE (plan_handle_id_goes_here)

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

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

DBCC FREESYSTEMCACHE ('ALL') WITH MARK_IN_USE_FOR_REMOVAL;

2
порада використовувати підказку щодо плану не все одно.
Рем Русану

1
Я виявив це після того, як мій запит магічно оновив поганий план, але я планую перевірити його наступного разу. Підказка щодо плану не допомагає, якщо запит страждає від "необов'язково-itis" - там, де він має багато необов'язкових параметрів і він був оптимізований для одного набору, тоді запустіть для іншого набору. Не існує оптимального плану, який би можна було долучити до такого запиту. Існує оптимальний план для одного набору параметрів, що, в свою чергу, жахливо для іншого набору параметрів.
Nick.McDermaid

6

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

Ви не можете видалити певний запис кеша, але ви можете очистити цілий пул кешу DBCC FREESYSTEMCACHE(cachename/poolname).

Ви можете отримати ім’я кеша поганого плану запитів, якщо у вас є ручка плану (від sys.dm_exec_requests.plan_handle для сесії_id, яка перебуває в проблемі під час виконання, або від виконання повідомлення sys.dm_exec_query_stats ):

select ce.name
from sys.dm_exec_cached_plans cp
join sys.dm_os_memory_cache_entries ce on cp.memory_object_address = ce.memory_object_address
where cp.plan_handle = @bad_plan

Однак усі плани SQL мають назву "Плани SQL", що робить вибір потрібного для DBCC FREESYSTEMCACHE ... складним вибором.

Оновлення

Не забудьте, забули DBCC FREEPROCCACHE(plan_handle), так, це спрацює.


1
Можливість передавати план плану в DBCC FREEPROCCACHE доступна в SQL Server 2008, а не в SQL Server 2005.
Маріо

Що значить , якщо sys.dm_exec_cached_plansнемає запису в ньому для plan_handleз sys.dm_exec_requests?
Джонатан Гілберт

@JonathanGilbert це означає, що план не був кешований, або він був виселений з кешу. Дивіться docs.microsoft.com/en-us/sql/relational-databases/…
Remus Rusanu

Отже, для підтвердження, хоча я тільки почав виконувати цей запит , і запит не має жодної підказки, щоб не кешувати його, він може бути кешований, оскільки SQL Server прийняв значення значення, щоб не кешувати його? Це не було б тому, що воно все ще працює, правда? Якщо він вирішить кешувати план, то він буде кешований прямо з того місця, коли запит починає працювати?
Джонатан Гілберт

1

Рішення FREEPROCCACHE чудово, але більш прямим способом цього є використання OPTION (RECOMPILE) на вашій SQL String (ви згадали, що це не SP), це повідомляє Двигуну свій план єдиного використання, тому що, ймовірно, ви підозрюєте є параметр Sniffing або ваша статистика різко відрізняється від запуску до запуску, і ви підозрюєте, що це проблема поганого кешованого плану.

DECLARE @SQL NVARCHAR(4000)
SELECT @SQL = 'SELECT * FROM Table WHERE Column LIKE @NAME OPTION (RECOMPILE)'
EXEC sp_executesql @SQL, N'@NAME varchar(15)', 'MyName' 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.