以前總結過一篇文章SQL SERVER中什麼情況會導致索引查找變成索引掃描 介紹了幾種索引查找(Index Seek)變成索引掃描(Index Scan)的情形。昨天寫一篇文章的時候,也遇到了一個讓人奇怪的執行計劃。一時沒有想明白為什麼優化器會選擇聚集索引掃描。案例詳情請見SQL Server OP... ...
以前總結過一篇文章SQL SERVER中什麼情況會導致索引查找變成索引掃描 介紹了幾種索引查找(Index Seek)變成索引掃描(Index Scan)的情形。昨天寫一篇文章的時候,也遇到了一個讓人奇怪的執行計劃。一時沒有想明白為什麼優化器會選擇聚集索引掃描。案例詳情請見SQL Server OPTION (OPTIMIZE FOR UNKNOWN) 測試總結 。 如下所示,測試環境為SQL Server 2014,資料庫為AdventureWorks2014
CREATE PROCEDURE test (@pid int)
AS
SELECT * FROM [Sales].[SalesOrderDetail]
WHERE ProductID = @pid OPTION (OPTIMIZE FOR UNKNOWN);
[Sales].[SalesOrderDetail]的索引信息如下如下。其實這裡優化器選擇聚集索引掃描是因為Cost緣故。因為走非聚集索引查找(Index Seek)的話,Key Lookup的開銷較大。整體開銷比聚集索引掃描還大。我們可以測試驗證一下
如下所示,我們新增一個SQL語句,強制其走索引查找(具體索引為IX_SalesOrderDetail_ProductID),然後執行對比查看執行計劃的開銷
ALTER PROCEDURE test (@pid int)
AS
SELECT * FROM [Sales].[SalesOrderDetail]
WHERE ProductID = @pid OPTION (OPTIMIZE FOR UNKNOWN);
SELECT * FROM [Sales].[SalesOrderDetail] WITH (INDEX =IX_SalesOrderDetail_ProductID)
WHERE ProductID = @pid;
GO
如下測試所示,兩種實際執行計劃的開銷比為 22% VS 78%。 所以優化器肯定會選開銷小的執行計劃。也就是說如果優化器發現當索引查找時,如果Key Lookup開銷過大,那麼優化器會選擇聚集索引索引掃描。 這個案例就是一個活生生的案例。 也許有人會反問:不是Index Seek效率表Index Scan要高嗎?你這有點不合邏輯,註意,這個特定條件下,雖然Index Seek變成 Index Scan,但是你註意一下上下文,索引變了, 從IX_SalesOrderDetail_ProductID變成了聚集索引PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID 。
總結: 任何現象背後都有一定的規律,有時候,只要你靜下心來,仔細分析一下。就能一窺究竟。如果總是不問為什麼,那麼你總是不瞭解背後原理!也就永遠止步不前!