如何从SQL Server查询caching中删除特定的错误计划?

我们有一个特定的SQL Server 2008查询(不是存储过程,但是相同的SQLstring – 每5分钟执行一次)间歇性地caching非常糟糕的查询计划。

这个查询通常运行几毫秒,但是这个糟糕的查询计划需要30多秒。

如何从SQL Server 2008中手动删除一个错误的caching查询计划 ,而不会吹走生产数据库服务器上的整个查询caching?

    我想出了一些事情

    select * from sys.dm_exec_query_stats 

    将显示所有caching的查询计划。 不幸的是,那里没有显示SQL文本。

    但是,您可以像这样将SQL文本join到计划中:

     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) 

    从查询计划caching中删除每个查询计划。 不完全简单或方便,但它似乎工作..

    编辑:倾倒整个查询caching也将工作,并且是不那么危险的,至less在我的经验:

     DBCC FREESYSTEMCACHE ('ALL') WITH MARK_IN_USE_FOR_REMOVAL; 

    如果你知道这个好计划是怎么样的,那么只需要使用一个计划提示 。

    您无法删除特定的caching条目,但可以使用DBCC FREESYSTEMCACHE(cachename/poolname)清理整个caching池。

    如果您有计划句柄(从sys.dm_exec_requests.plan_handle执行期间的session_id遇到麻烦,或者从sys.dm_exec_query_stats执行后),则可以获取错误查询计划的caching名称:

     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 FREESYSTEMCACHEselect了一个合适的select。

    更新

    没关系,忘了DBCC FREEPROCCACHE(plan_handle) ,是的,这将工作。

    FREEPROCCACHE解决scheme是好的,但更直接的方法是在您的SQLstring上使用OPTION(RECOMPILE) (您提到它不是SP),这会告诉引擎它是单用途计划,因为您可能怀疑有参数嗅探,或者你的统计信息与运行运行有很大的不同,你怀疑是一个坏的caching计划问题。

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