Sql-Server

使用多列創建索引 - 我應該盡可能多地組合嗎?

  • February 28, 2018

在創建索引時,尤其是那些具有多列的索引時,我是否應該盡可能多地組合索引中的列?

我已經在統計資訊上執行了一個腳本來獲取失去的索引,並且有一些建議,例如:

CREATE INDEX [IX_Tbl_ContractId_OpenClosedStatus] ON [tbl]
([ContractId], [OpenClosedStatus]) INCLUDE ([Id], [StringId], [DateNextDeadline])

CREATE INDEX [IX_Tbl_ContractId_OpenClosedStatus] ON [tbl]
([ContractId], [OpenClosedStatus]) INCLUDE ([Id], [DateNextDeadline])

CREATE INDEX [IX_Tbl_ContractId_OpenClosedStatus] ON [tbl]
([ContractId], [OpenClosedStatus]) INCLUDE ([Id], [ClientId], [DateNextDeadline])

它們都有相同的[Id][DateNextDeadline],並且它們都在相同的兩個主要列上建立索引。

在這種情況下,我是否應該使用 SQL Server 使用相同的列索引創建一個索引,([Id], [StringId], [ClientId], [DateNextDeadline])並根據查詢選擇包含列?還是僅在完全匹配時才使用索引?所以我需要創建三個索引?

基於這 3 個具體建議,我會使用

CREATE INDEX [IX_Tbl_ContractId_OpenClosedStatus] ON [tbl]
([ContractId], [OpenClosedStatus]) INCLUDE ([Id], [ClientId], [DateNextDeadline],[StringID])

等式/不等式列是相同的,這是較大的部分。SQL Server 應該將它用於具有所有或這些包含列的子集的任何查詢。

當然,您可以通過一組嚴格的測試查詢來執行它來驗證:)

在這種情況下,我是否應該使用 (

$$ Id $$, $$ StringId $$,$$ ClientId $$,$$ DateNextDeadline $$) 並且 SQL Server 是否會根據查詢使用相同的列索引並選擇包含列?還是僅在完全匹配時才使用索引?所以我需要創建三個索引?

如果查詢計劃中有索引查找,則使用覆蓋索引,否則不使用。

我只想回答“ Multiple column or single column index and ordering of index in composite index

索引將被利用或不依賴於Query Optimizer (QO)或該列的選擇性。

假設在查詢中如果返回更多行數,那麼如果 QO 發現 Index Scan 比 Index Seek 更具成本效益,則可以索引 Scan。

所以索引列在聚集索引或非聚集索引中應該更具選擇性,以便 QO 選擇 Index Seek。

所以在composite index大多數selective index情況下應該是向左的。換句話說,“它應該是最有選擇性的順序”。

CREATE INDEX [IX_Tbl_ContractId_OpenClosedStatus] ON [tbl]
([ContractId], [OpenClosedStatus]) INCLUDE (ID,[StringId],[ClientId], [DateNextDeadline])

如果 ID 是聚集索引,則從覆蓋列表中刪除。

我有一個在兩列上過濾的查詢

where [ContractId]=? and [OpenClosedStatus]=?

如果ContractIdOpenClosedStatus 複合索引中的列順序更具選擇性。

現在 QO 將決定它是否有足夠的選擇性來進行索引搜尋或進行索引掃描。

這也取決於其他因素。

如果我有另一個查詢我將在哪裡使用

只要where [OpenClosedStatus]=?

在這裡,如果OpenClosedStatus選擇性足夠,那麼可能在上面創建單獨的索引[OpenClosedStatus]是不錯的選擇。如果OpenClosedStatus選擇性不夠,那麼在此列創建單獨的索引沒有意義。

假設OpenClosedStatusbit type 那麼它可能會返回很多行,所以它的選擇性不夠。

但在復合索引OpenClosedStatus中可能工作正常。IX_Tbl_ContractId_OpenClosedStatus

如果我只查詢where DateNextDeadline

因此,在我們的範例中,它永遠不會命中索引,因為該列上沒有索引,它包含在cover index.cover 索引中,目的是別的。

我有使用所有三列的查詢,那麼我的索引會像,

CREATE INDEX [IX_Tbl_ContractId_OpenClosedStatus_1] ON [tbl]
([ContractId],[DateNextDeadline], [OpenClosedStatus]) INCLUDE (ID,[StringId],[ClientId] )

where [ContractId]=? and [DateNextDeadline]=? [OpenClosedStatus]=?

假設所有列都具有足夠的選擇性,並且如果您有不同的查詢,其中任何或所有列將用於過濾,那麼您可以創建單獨的索引。

所以首先了解你的工作量,

i) 在“加入、位置、排序、分組”條件下使用哪一列。

ii) 哪個查詢將被非常頻繁地使用以及它的重要性。

iii)如果表具有靜態且行數較少,則指向在該表上創建索引。

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