1. 程式人生 > >Key Lookup開銷過大導致聚集索引掃描

Key Lookup開銷過大導致聚集索引掃描

2018-09-21 15:11 by 瀟湘隱者, ... 閱讀, ... 評論, 收藏, 編輯

介紹了幾種索引查詢(Index Seek)變成索引掃描(Index Scan)的情形。昨天寫一篇文章的時候,也遇到了一個讓人奇怪的執行計劃。一時沒有想明白為什麼優化器會選擇聚集索引掃描。案例詳情請見SQL Server OPTION (OPTIMIZE FOR UNKNOWN) 測試總結 。如下所示,測試環境為SQL Server 2014,資料庫為AdventureWorks2014

CREATEPROCEDURE test(@pid int)

AS

SELECT*

FROM [Sales].[SalesOrderDetail]

WHERE ProductID = @pid OPTION (OPTIMIZE FOR UNKNOWN);

clip_image001

[Sales].[SalesOrderDetail]的索引資訊如下如下。其實這裡優化器選擇聚集索引掃描是因為Cost緣故。因為走非聚集索引查詢(Index Seek)的話,Key Lookup的開銷較大。整體開銷比聚集索引掃描還大。我們可以測試驗證一下

clip_image002

如下所示,我們新增一個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%VS78%。所以優化器肯定會選開銷小的執行計劃。也就是說如果優化器發現當索引查詢時,如果Key Lookup開銷過大,那麼優化器會選擇聚集索引索引掃描。 這個案例就是一個活生生的案例。 也許有人會反問:不是Index Seek效率表Index Scan要高嗎?你這有點不合邏輯,注意,這個特定條件下,雖然Index Seek變成 Index Scan,但是你注意一下上下文,索引變了, 從IX_SalesOrderDetail_ProductID變成了聚集索引

PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID 。

clip_image003

總結: 任何現象背後都有一定的規律,有時候,只要你靜下心來,仔細分析一下。就能一窺究竟。如果總是不問為什麼,那麼你總是不瞭解背後原理!也就永遠止步不前!