Sql-Server

非集群索引中包含哪些更重要的列 - 來自 Group by 或 Where?

  • September 23, 2021

我正在考慮向NONCLUSTERED INDEXSQL Server 2016 中的表添加一個。我發現大多數查詢都引用WHERE如下子句:

WHERE varcharColumn <> '' 
and varcharColumn2 = '2' 
and varcharColumn3 in ('A','B')

但大多數查詢都有GROUP BY如下聲明:

GROUP BY varcharColumn4, varcharColumn5, varcharColumn6

所以我們對不同的列進行分組,而不是在WHERE子句中。

NONCLUSTERED INDEX為該表添加的好方法是什麼?

通常,WHERE 子句在 GROUP BY 之前處理,因此請考慮哪個會產生最大效果。如果您的表中有 1,000,000 行,並且您的 WHERE 子句將過濾掉其中的大部分,那麼索引 WHERE 子句(首先),特別是在過濾掉更多行時最有效的列。如果 WHERE 子句不會過濾掉太多,那麼排序可能更重要,因此 GROUP BY 的索引可能最有意義。

顯然,最好的方法是針對不同的代表性工作負載進行測試。

我會推薦來自Brent的關於查詢調整和思考的部落格和培訓,比如 SQL Server,以獲得思考這類問題的好方法。

**分組最好通過排序輸入完成,所以我們真的希望保持從索引中的有序讀取。**這意味著不能使用不等式列,因為這會打亂排序。平等列仍應放在首位。

分解您目前的查詢,我們可以嘗試估計哪些列最有用:

WHERE varcharColumn <> ''
-- prob not useful as a key column because it's an inequality
and varcharColumn2 = '2'
-- should be leading column as it's equality
and varcharColumn3 in ('A','B')
-- IN is an OR, so not that useful
GROUP BY varcharColumn4, varcharColumn5, varcharColumn6
-- grouping is best when sorted, so these should be next

這意味著最好的索引可能是

(varcharColumn2, varcharColumn4, varcharColumn5, varcharColumn6)
 INCLUDE (varcharColumn, varcharColumn3)

另一種可能的選擇是

(varcharColumn2, varcharColumn3, varcharColumn4, varcharColumn5, varcharColumn6)
 INCLUDE (varcharColumn)

但是,這只有在編譯器選擇索引聯合策略時才可能起作用,而它可能不會這樣做。

您可以使用以下程式碼強制索引聯合

SELECT ...
FROM
(
   SELECT varcharColumn2, varcharColumn3, varcharColumn4, varcharColumn5, varcharColumn6, varcharColumn
   FROM YourTable
   WHERE varcharColumn <> '' 
     and varcharColumn2 = '2' 
     and varcharColumn3 = 'A'
   UNION ALL
   SELECT varcharColumn2, varcharColumn3, varcharColumn4, varcharColumn5, varcharColumn6, varcharColumn
   FROM YourTable
   WHERE varcharColumn <> '' 
     and varcharColumn2 = '2' 
     and varcharColumn3 = 'B'
) t
GROUP BY varcharColumn4, varcharColumn5, varcharColumn6

**如果最終結果集可能很小,**並且不等式列正在執行大部分過濾,則可能值得將其作為關鍵列。這意味著將需要排序或散列來分組,但在一個小集合上這沒什麼大不了的。

(varcharColumn2, varcharColumn)
 INCLUDE (varcharColumn4, varcharColumn5, varcharColumn6, varcharColumn3)

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