使用多列創建索引 - 我應該盡可能多地組合嗎?
在創建索引時,尤其是那些具有多列的索引時,我是否應該盡可能多地組合索引中的列?
我已經在統計資訊上執行了一個腳本來獲取失去的索引,並且有一些建議,例如:
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]=?
如果
ContractId
比OpenClosedStatus
複合索引中的列順序更具選擇性。現在 QO 將決定它是否有足夠的選擇性來進行索引搜尋或進行索引掃描。
這也取決於其他因素。
如果我有另一個查詢我將在哪裡使用
只要
where [OpenClosedStatus]=?
在這裡,如果
OpenClosedStatus
選擇性足夠,那麼可能在上面創建單獨的索引[OpenClosedStatus]
是不錯的選擇。如果OpenClosedStatus
選擇性不夠,那麼在此列創建單獨的索引沒有意義。假設
OpenClosedStatus
是bit typ
e 那麼它可能會返回很多行,所以它的選擇性不夠。但在復合索引
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)如果表具有靜態且行數較少,則指向在該表上創建索引。