Sql-Server
ORDER BY 中的冗餘欄位用於高效排序?
假設我有一個
SortTest
包含欄位Data1
、Data2
、Sort1
和的表Sort2
,Key1
並且Key2
需要執行以下查詢:SELECT TOP 1 Data1, Data2 FROM SortTest WHERE Key1 = @key1 AND Key2 = @key2 ORDER BY Sort1, Sort2
為了優化它,我為以下序列創建了一個索引
Key1, Key2, Sort1, Sort2
但是執行計劃仍然顯示索引掃描而不是查找,因為它不能有效地對不啟動索引的欄位序列進行排序。因此,為了優化查詢,我必須將它們的鍵添加到
ORDER BY
子句中,這當然是多餘的:SELECT TOP 1 Data1, Data2 FROM SortTest WHERE Key1 = @key1 AND Key2 = @key2 ORDER BY Key1, Key2, Sort1, Sort2
查詢現在按預期工作,但我想知道它是否可以以更優雅的方式進行優化。
更正:
我意識到當我簡化上面的查詢時,有一個嚴重的錯誤。其中一個條件有一個
IN
, not=
,所以真正的查詢(產生不同的計劃)有這個:WHERE Key1 = @key1 AND Key2 = IN (@key2a, @key2b, ...)
這解釋了(
key2
結果中的值不是固定的,因此不同ORDER BY
可能導致不同的輸出)和計劃差異。讓我們感謝每個人的幫助,並為混亂道歉。
這實際上非常簡單。執行查詢時,SQL Server 首先查找要返回的行。如果存在 WHERE 子句元素,則在系統甚至考慮使用用於 ORDER BY 的索引之前檢查這些元素。
如果您考慮各種可能性,這是完全有道理的。
- WHERE 子句中的任何內容都沒有索引——必須執行表或聚集索引掃描
- WHERE 子句中一個元素的索引——掃描由一個元素過濾的所有行以查找其他匹配項
- WHERE 子句中所有元素的索引——根據索引選擇所有行。必須在記錄中查找數據。
- WHERE 子句中所有元素的索引,以及數據元素的 INCLUDE – 根據索引選擇所有行。使用 INCLUDE 語句中的數據元素。
- 對 WHERE 子句中的所有元素加上所有數據元素進行索引——根據索引選擇所有行,並使用索引中嵌入的數據元素。
- 僅對數據元素建立索引——如果有聚集索引,則在該索引上查找數據將是最有效的。未知查詢優化器是否會掃描數據元素索引以嘗試使數據檢索更高效,但值得懷疑。
基本上,你最好的索引是:
CREATE INDEX MyIndex ON MyTable (Key1, Key2, Sort1, Sort2)
將根據關鍵資訊(索引的設計目的)搜尋數據,然後使用已在索引中排序的附加資訊進行輸出。
已編輯