第三方套件、加密存儲過程、廠商鎖定代碼等場景下,DBA 無法直接修改 SQL 文本加入 Hint。SQL Server 2005 引入計劃指南,允許在資料庫層面為特定查詢綁定優化提示,實現「零代碼變更」調優。
| 類型 | 匹配範圍 | 典型場景 |
|---|---|---|
| OBJECT | 預存程序、函數、觸發器內的查詢 | 可識別模組名稱的內部查詢 |
| SQL | 獨立批次/動態 SQL(sp_executesql) | 應用程式內嵌參數化查詢、ORM 產出 SQL |
| TEMPLATE | 參數化形式的獨立查詢 | 強制參數化資料庫下的模板化查詢 |
sp_create_plan_guideEXEC sp_create_plan_guide
@name = N'GuideName', -- 指南名稱
@stmt = N'SELECT ...', -- 要匹配的完整 SQL 文本(必須逐字一致)
@type = N'SQL', -- OBJECT / SQL / TEMPLATE
@module_or_batch = NULL, -- OBJECT 類型時指定模組名,其餘 NULL
@params = N'@Param1 int, ...', -- SQL/TEMPLATE 類型:參數定義字串
@hints = N'OPTION (RECOMPILE)'; -- 要附加的 Hint 子句
USE AdventureWorks;
GO
-- 第一次執行:ProductID=870(高選擇性,4688 行),優化器選擇 Table Scan
EXEC sp_executesql
@stmt = N'SELECT * FROM Sales.SalesOrderDetail WHERE ProductID = @ProductID',
@params = N'@ProductID int', @ProductID = 870;
-- 第二次執行:ProductID=897(極低選擇性,2 行),卻復用 Table Scan 計畫
EXEC sp_executesql
@stmt = N'SELECT * FROM Sales.SalesOrderDetail WHERE ProductID = @ProductID',
@params = N'@ProductID int', @ProductID = 897;
結果:第二次執行本應用 Index Seek,卻因計畫快取復用導致全表掃描,效能差異可達數十倍。
EXEC sp_create_plan_guide
@name = N'Fix_SalesOrderDetail_ParameterSniffing',
@stmt = N'SELECT * FROM Sales.SalesOrderDetail WHERE ProductID = @ProductID',
@type = N'SQL',
@module_or_batch = NULL,
@params = N'@ProductID int',
@hints = N'OPTION (RECOMPILE)';
GO
ProductID=870 仍用 Table Scan,ProductID=897 改為 Index Seek。SP:Recompile 事件,確認每次執行前重新編譯。sys.plan_guides 確認指南存在。SELECT name, type, module_or_batch, params, hints, is_disabled, create_date, modify_date
FROM sys.plan_guides;
sp_control_plan_guide-- 停用單一指南
EXEC sp_control_plan_guide N'DISABLE', N'Fix_SalesOrderDetail_ParameterSniffing';
-- 啟用單一指南
EXEC sp_control_plan_guide N'ENABLE', N'Fix_SalesOrderDetail_ParameterSniffing';
-- 刪除單一指南
EXEC sp_control_plan_guide N'DROP', N'Fix_SalesOrderDetail_ParameterSniffing';
-- 批次操作
EXEC sp_control_plan_guide N'DISABLE ALL', NULL;
EXEC sp_control_plan_guide N'DROP ALL', NULL;
@stmt 必須與應用提交的 SQL 逐字一致(含空白、換行、大小寫),建議從 Profiler/Query Store 擷取確切文本。計劃指南是 DBA 「隔空施法」的利器,能在完全不觸動應用程式碼的前提下,為特定查詢注入優化提示。但大權在握責任重大:必須建立嚴格的變更管理流程、完整文記錄與定期審查機制,防止「指南腐爛」反而拖累效能。