執行計劃生成后會存儲在plan cache中,以便重用,如果計劃緩存從來都沒有被重用 過,將會造成內存資源的浪費,這有可能是由于非參數化的Ad-hoc (即席查詢)引起的。 當執行代碼時,會產生一個hash值,用于匹配計劃緩存中的hash值,相同的hash值代表 語句是相同的。如果執行一個存儲過程,會按照存儲過程名來創建hash值,如果在存儲過 程之外執行代碼(Ad-hoc T-SQL),那么hash值會根據整個語句產生。你的代碼有一點點字 面上的改變,都會產生不同的hash值,導致計劃無法重用。當有大量Ad-hoc執行時,會 導致計劃緩存的膨脹。
針對這類問題,可以考慮使用存儲過程、函數或者參數化Ad-hoc,但是有時候的確沒 有辦法,必須使用非參數化的Ad-hoc。從 SQL Server 2008開始,引人了一個“針對即席 工作負荷進行優化”的選項,如圖3-9所示。
找到該選項的具體步驟是:右鍵實例,然后選擇“屬性",再選擇“高級",之后把圖3-9
箭頭處的False改成True。下面是針對該選項的官方解釋:
?
“針對即席工作負荷進行優化”選項用于提高包含許多一次性臨時批處理的工作負荷計
劃緩存的效率。如果該選項設置為True,則數據庫引擎將在首次編譯批處理時在計劃緩存 中存儲一個編譯的小計劃存根,而不是存儲完全編譯的計劃。在這種情況下,不會讓未重
復使用的編譯計劃填充計劃緩存,從而有助于緩解內存壓力。
編譯的計劃存根使數據庫引擎能夠識別此臨時批處理以前已經編譯過,但只存儲了編
譯計劃存根,因此當再次調用(編譯或執行)此批處理時,數據庫引擎會對此批處理進行編
譯,從計劃緩存中刪除編譯計劃存根并將完全編譯的計劃添加到計劃緩存中。
將 “針對即席工作負荷進行優化”設置為1 只會影響新計劃,而已在計劃緩存中的計
劃不受影響。
編譯計劃存根是sys.dm_exec_cached_plans目錄視圖顯示的cacheobjtype之一。它具有
唯一的SQL句柄和計劃句柄。編譯計劃存根沒有與其關聯的執行計劃,并且查詢計劃句柄
不會返回XML顯示計劃。
可以用下面的腳本來查看緩存對象的對應內存數。
SELECT objtype AS 'Cached Object Type * , COUNT(*) AS 'Number of Plans', SUM(CAST{size_in_bytes AS BIGINT)) / 1024 / 1024 AS 'Plan Cache Size (MB)', AVG(usecounts) AS 'Avg Use Count * FROM sys.dm_exec_cached_plans GROUP BY objtype
在筆者計算機上的結果如圖3-10所示。
?
?在 沒 有 開 啟 上 面 選 項 的 系 統 中 ,Ad-hoc通 常 是 內 存 占 用 最 多 的 部 分 。所 以 從 SQL Server 2008開 始 ,建議開啟這個選項。