Sql-Server

ORDER BY 中的冗餘欄位用於高效排序?

  • April 10, 2019

假設我有一個SortTest包含欄位Data1Data2Sort1和的表Sort2Key1並且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)

將根據關鍵資訊(索引的設計目的)搜尋數據,然後使用已在索引中排序的附加資訊進行輸出。

已編輯

引用自:https://dba.stackexchange.com/questions/234460