SQL server運行到一定的時候, 執行計劃的緩存可能會相當大,有些能到幾個GB的大
sql server運行到一定的時候, 執行計劃的緩存可能會相當大,有些能到幾個gb的大小。這個時候假設某個語句比較復雜而且sql server 生成的執行計劃不夠優化,你希望把該執行計劃的緩存清除使得sql server能夠重新編譯該語句。該如何做呢?
如果是存儲過程則很好辦,直接使用sp_recompile就可以了,如下所示。如果參數是表,那么所有用到該表的存儲過程或trigger都會重新編譯,從而把原來的plan 替換掉:
USE AdventureWorks;
GO
EXECsp_recompileN’Sales.Customer’;
GO
如果是一般的語句呢? 比如下面的語句:
use AdventureWorks
go
SELECT*FROM Sales.SalesOrderHeader h, Sales.Customer c,Sales.SalesTerritory t
WHERE h.CustomerID = c.CustomerID
AND c.TerritoryID = t.TerritoryID
AND CountryRegionCode = N‘CA’;
我執行上面的語句幾次后,觀察下執行計劃的緩存:
SELECT usecounts,text,plan_handle,*FROMsys.dm_exec_cached_plans cp
CROSSAPPLY sys.dm_exec_query_plan(cp.plan_handle)
CROSSAPPLY sys.dm_exec_sql_text (cp.plan_handle)
wheretextlike
‘%SELECT * FROM Sales.SalesOrderHeader h, Sales.Customer c,Sales.SalesTerritory t
WHERE h.CustomerID = c.CustomerID
AND c.TerritoryID = t.TerritoryID
AND CountryRegionCode%’;
得到結果如下:
Usecounts表示該語句被執行了7次。 如果這個語句的執行計劃不好,如何刪除它呢?
如果是SQL server 2008 R2就很好辦,直接使用DBCC FREEPROCCACHE然后傳入plan handle如即可,如:
DBCC FREEPROCCACHE(0x060001002903DC0B4001B887000000000000000000000000)
但是SQL server 2005的FREEPROCCACHE并沒有這個用法。 SQL 2005里面如果運行DBCC FREEPROCCACHE那么所有的緩存都會被清空了。這對性能的影響比較大,因為SQL server 要對所有的語句重新編譯然后重新生成緩存。SQL server 2005里面有沒有其他方法只清除特定的語句的緩存呢?
有的,答案就使用使用plan guide如下:
sp_create_plan_guide
@name =? N‘recompile_Guide’,
@stmt =
N‘SELECT * FROM Sales.SalesOrderHeader h, Sales.Customer c,Sales.SalesTerritory t
WHERE h.CustomerID = c.CustomerID
AND c.TerritoryID = t.TerritoryID
AND CountryRegionCode = N”CA”;’,
@type = N‘SQL’,
@module_or_batch =NULL,
@params =NULL,
@hints = N‘OPTION (RECOMPILE)’
go
exec sp_control_plan_guide N‘drop’,N‘recompile_Guide’
上面的sp_create_plan_guide使用RECOMPILE參數,意思是說,每次碰到該語句,必須重新編譯。sp_create_plan_guide運行后,該語句的執行計劃緩存就被刪除了,下次該語句再次執行就會重新編譯。那么我為什么馬上又刪除這個plan guide呢?因為該語句的緩沖被清除后,我不希望該語句每次執行都重新編譯,所以我刪除了它,畢竟我執行sp_create_plan_guide的目的是刪除該語句的執行計劃緩存而已。所以如果你使用同樣的手段,務必記得立即把sp_create_plan_guide建立的guide刪除。