參考文獻:
執行計畫的緩衝和重新使用
重新編譯執行計畫
根據資料庫新狀態的不同,資料庫中的某些更改可能導致執行計畫效率降低或無效。SQL Server 將檢測到使執行計畫無效的更改,並將計劃標記為無效。此後,必須為執行查詢的下一個串連重新編譯新的計劃。導致計劃無效的情況包括:
- 對查詢所引用的表或視圖變更(ALTER TABLE 和 ALTER VIEW)。
- 對執行計畫所使用的任何索引變更。
- 對執行計畫所使用的統計資訊進行更新,該更新可能是從語句(如 UPDATE STATISTICS)中顯示產生,也可能是自動產生的。
- 刪除執行計畫所使用的索引。
- 顯式調用 sp_recompile。
- 對鍵的大量更改(其他使用者對由查詢引用的表使用 INSERT 或 DELETE 語句所產生的修改)。
- 對於帶觸發器的表,插入的或刪除的表內的行數顯著增長。
- 使用 WITH RECOMPILE 選項執行預存程序。
為了使語句正確,或要獲得可能更快的查詢執行計畫,大多數都需要進行重新編譯。
在 SQL Server 2000 中,只要批處理中的語句導致重新編譯,就會重新編譯整個批處理,無論此批處理是通過預存程序、觸發器、即席批查詢,還是通過預定義的語句進行提交。在 SQL Server 2005 中,只有在批處理中導致重新編譯的語句才會被重新編譯。由於這種差異,SQL Server 2000 和 SQL Server 2005 中的重新編譯計數不可比較。另外,由於 SQL Server 2005 擴充了功能集,因此,具有更多重新編譯類型。
語句級重新編譯有助於提高效能,因為在大多數情況下,只有少數語句導致了重新編譯並造成相關損失(指 CPU 時間和鎖)。因此,避免了批處理中其他不必重新編譯的語句的這些損失。
SQL Server Profiler SP:Recompile 跟蹤事件在 SQL Server 2005 中報告語句級重新編譯。此跟蹤事件在 SQL Server 2000 中僅報告批處理重新編譯。此外,在 SQL Server 2005 中,將填充此事件的 TextData 列。因此,已不再需要 SQL Server 2000 中必須跟蹤 SP:StmtStarting 或SP:StmtCompleted 以擷取導致重新編譯的 Transact-SQL 文本的做法。
SQL Server 2005 也添加了一個新跟蹤事件,稱為 SQL:StmtRecompile,它報告語句級重新編譯。此跟蹤事件可用於跟蹤和調試重新編譯。SP:Recompile 僅針對預存程序和觸發器產生,而 SQL:StmtRecompile 則針對預存程序、觸發器、即席批查詢、使用 sp_executesql 執行的批處理、已準備的查詢和動態 SQL 產生。
SP:Recompile 和 SQL:StmtRecompile 的 EventSubClass 列都包含一個整數代碼,用以指明重新編譯的原因。下表包含每個代碼號的意思。
| EventSubClass 值 |
說明 |
1 |
架構已更改。 |
2 |
統計資訊已更改。 |
3 |
編譯已延遲。 |
4 |
SET 選項已更改。 |
5 |
暫存資料表已更改。 |
6 |
遠程行集已更改。 |
7 |
FOR BROWSE 許可權已更改。 |
8 |
查詢通知環境已更改。 |
9 |
分區視圖已更改。 |
10 |
遊標選項已更改。 |
11 |
已請求 OPTION (RECOMPILE)。 |
注意當 AUTO_UPDATE_STATISTICS 資料庫選項被設定為 ON 時,如果查詢以表或索引檢視表為目標,而表或索引檢視表的統計資訊自上次執行後已更新或基數已發生很大變化,查詢將被重新編譯。此行為適用於標準使用者定義表、暫存資料表以及由 DML 觸發程序建立的
inserted 和
deleted表。如果過多的重新編譯影響到查詢的效能,請考慮將此設定更改為 OFF。當 AUTO_UPDATE_STATISTICS 資料庫選項設定為 OFF 時,不會因統計資訊或基數的更改而發生任何重新編譯,但是,由 DML INSTEAD OF 觸發器建立的
inserted 和
deleted 表除外。因為這些表是在
tempdb 中建立的,因此,是否重新編譯訪問這些表的查詢取決於
tempdb 中 AUTO_UPDATE_STATISTICS 的設定。請注意,在 SQL Server 2000 中,即使此設定為 OFF,查詢仍然會基於 DML 觸發程序
inserted 和
deleted 表的基數變化進行重新編譯。有關禁用 AUTO_UPDATE_STATISTICS 的詳細資料,請參閱索引統計資訊。