[SQL SERVER] 多個索引 vs 單一寬索引
實務上最快提高查詢效能莫過於建立和設計正當索引,
依照相關TSQL建立設計正確索引所帶來效能效益我個人認為是最高的,
這篇來討論一個索引設計問題,
我們知道大部分情況下index seek優於index scan(大海撈針),
假設今天有一TSQL如下(where 條件有三個):
設計1:依照條件建立三個nonclustered index
因為需要使用index join,所以TSQL改寫如下
執行計畫
雖然一開始都個別使用index seek 運算子,但hash join運算子成本高的可怕,
並且出現遺漏索引警告。
統計資料
設計2:個別建立三個篩選索引(SQL2008後提供)
執行計畫
整體執行計畫和設計1相差不多(少了點陣圖運算子),但依然還是可以看到hash join高成本和遺漏索引資訊。
ps:以這篩選索引來說少了彈性,只要查詢條件一有改變,篩選索引馬上無用武之地,
如果資料表沒有其他索引的話將導致出現無法建立執行計畫錯誤。
統計資料
使用篩選索引降低很多I/O和CPU。
設計3:建立單一寬索引 with include
執行計畫
執行計畫複雜度降低,而且也沒有任何遺漏索引訊息,但是依然還是使用平行執行計畫。
統計資料
I/O和CPU都有比面兩種設計來的低很多。
設計3.1:建立單一寬索引 without include
ps:執行計畫和統計資料都和設計3相同,但是該索引大小比設計3來的大,
效率比設計3來的低(acid問題)。
設計4:建立單一篩選索引
執行計畫
執行計畫不複雜是我們樂於看到的結果。
統計資料
I/O邏輯讀取目前是最低的,不過這篩選索引設計缺點前面有提到過了(缺乏彈性)。
調校
為了兼具彈性和效能,我決定從設計3下手調校,設計3執行計畫可看到是使用平行計畫,
查看該執行計劃發現最大問題在於資料型別不同所導致,
因為設計4執行計畫只有單一索引搜尋運算子,換句話說該執行計畫或許是最佳執行計畫,
修正TSQL並執行設計3索引
執行計畫
執行計畫和設計4相同。
統計資料
雖然I/O和CPU不如設計4來的優,但卻比設計4來的更有彈性,同時也比原本設計3更好。
結論:
1.盡量避免使用 Hint
現在SQL Server query optimize 比以前好太多,大部分情況下無需使用Hint來強制改變執行計畫,
當然Hint還是有存在價值,如果查詢有使用hint建議每個月或每一季再次確認執行計畫是否有所改變。
2.單一寬索引是比較好選擇
建立多個索引並透過index join將導致高CPU和I/O,這意味者增加資源競爭,
同時單一資料表中索引過多會影響新增、修改、刪除效能,
而這也表示可能帶來更多長lock問題
3.資料欄為請使用include
非索引鍵資料行可大幅降低I/O,因為可以不需存取資料表或Clustered Index,
便可直接在Nonclustered Index找到所有資料行,
同時可降低索引大小、而且Database Engine也不會考慮非索引鍵資料行大小(16個資料行、900bytes限制),
可說一舉多得。
4.是否需要Indexed View
索引設計中這也是需要考慮的,你可以參考我以前文章來決定是否需要
[SQL SERVER][Performance]善用Indexed View#1簡介
[SQL SERVER][Performance]善用Indexed View#2測試
5.索引鍵順序
雖然很多人都說順序不是那麼重要,但我個人認為到目前為止還是有那麼一些差異存在,
個人習慣把直接相等述詞排在最前面,如果述詞相同,則比較資料類型優先權(高的在前面),
如果資料類型相同,在比較長度大小(長度小的在前面)。
參考