討論時常提到 SQL Server 會選擇執行計畫成本較低的來跑,但其實會影響因素很多,本篇筆記以 [資料量] 和 [Key Lookup] 兩者來驗證,抓取過多資料和非叢集索引無法滿足所需資料,而必須透過 key lookup 抓取,兩者都是觀察執行計畫重點
在 AdvenureWork Sales.SalesOrderHeader Table 建立 IX_SalesOrderHeader_OrderDate 來記錄
use AdventureWorks2017
go
CREATE INDEX IX_SalesOrderHeader_OrderDate ON Sales.SalesOrderHeader (OrderDate)
WITH (DROP_EXISTING = ON);
case1:以單日 (20130701) 資料來觀察執行計畫
SELECT
SalesOrderNumber ,
OrderDate ,
CustomerID ,
SubTotal
FROM Sales.SalesOrderHeader
WHERE OrderDate BETWEEN '20130701' AND '20130701'
IX_SalesOrderHeader_OrderDate Index Seek 並輸出 43 筆資料後,利用 key lookup 取回 CustomerID 和 SubTotal 資料
case2:以單月 (201307) 資料來觀察執行計畫
SELECT
SalesOrderNumber ,
OrderDate ,
CustomerID ,
SubTotal
FROM Sales.SalesOrderHeader
WHERE OrderDate BETWEEN '20130701' AND '20130731'
PK_SalesOrderHeader_SalesOrderID Index Scan 並輸出 31,465 筆資料後,最後透過 Filter 來篩選資料至 1,740 筆
當日期區間拉長 (單日 => 單月,資料量增加) 時,SQL Server 選擇執行計畫成本較較低的 Clustered Index Scan (PK_SalesOrderHeader_SalesOrderID) + Filter 來跑
接下來透過 case3:以單月 (201307) 並強制跑 IX_SalesOrderHeader_OrderDate 來驗證 SQL Server 會選擇成本較低的執行計畫來跑
SELECT
SalesOrderNumber ,
OrderDate ,
CustomerID ,
SubTotal
FROM Sales.SalesOrderHeader WITH (INDEX(IX_SalesOrderHeader_OrderDate))
WHERE OrderDate BETWEEN '20130701' AND '20130731'
因為有 Index Hint,所以用 IX_SalesOrderHeader_OrderDate 並輸出 1,740 筆資料後,利用 key lookup 取回 CustomerID 和 SubTotal 資料
把 case2 和 case3 TSQL 放在一起跑,就可以很明顯比較出執行計畫成本差異