Назад | Перейти на главную страницу

Как удалить конкретный плохой план из кеша запросов SQL Server?

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

Этот запрос обычно выполняется за несколько миллисекунд, но с этим плохим планом запроса он занимает более 30 секунд.

Как мне сделать хирургическим путем удалить только один неверный кэшированный план запроса из SQL Server 2008, не удаляя весь кеш запросов на сервере производственной базы данных?

Я понял несколько вещей

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;

Если вы знаете, как выглядит хороший план, просто используйте подсказка плана.

Вы не можете удалить конкретную запись кеша, но вы можете очистить весь пул кеша с помощью DBCC FREESYSTEMCACHE(cachename/poolname).

Вы можете получить кеш-имя плохого плана запроса, если у вас есть дескриптор плана (из sys.dm_exec_requests.plan_handle для session_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), да, это сработает.

В БЕСПЛАТНО решение в порядке, но более простой способ сделать это - использовать ВАРИАНТ (РЕКОМЕНДУЕТСЯ) в вашей строке SQL (вы упомянули, что это не SP), это сообщает движку план однократного использования, потому что, вероятно, вы подозреваете, что есть анализ параметров или ваша статистика резко отличается от запуска к запуску, и вы подозреваете, что это плохое кеширование План выпуска.

DECLARE @SQL NVARCHAR(4000)
SELECT @SQL = 'SELECT * FROM Table WHERE Column LIKE @NAME OPTION (RECOMPILE)'
EXEC sp_executesql @SQL, N'@NAME varchar(15)', 'MyName'