2014-10-29 76 views
0

假設查詢正在過濾兩個字段並返回主鍵值。SQL:將主鍵添加到非唯一索引

SELECT RowIdentifier 
FROM Table 
WHERE QualifierA = 'exampleA' AND QualifierB = 'exampleB' 

假設聚簇索引不是的PrimaryKey將包含QualifierA和QualiferB通過加入RowIdentifier(情況A &情形B)來提供最好的服務的非唯一索引。或者僅僅包括它會更恰當(情景C)?

場景A:非唯一,非聚集

CREATE NONCLUSTERED INDEX IX_Table_QualifierA 
ON [dbo].[Table] ([QualifierA],[QualifierB],[RowIdentifier]) 

場景B:獨特的,非聚集

CREATE UNIQUE NONCLUSTERED INDEX IX_Table_QualifierA 
ON [dbo].[Table] ([QualifierA],[QualifierB],[RowIdentifier]) 

方案C:

CREATE NONCLUSTERED INDEX IX_Table_QualifierA 
ON [dbo].[Table] ([QualifierA],[QualifierB]) 
INCLUDE ([RowIdentifier]) 

最後我假設如果PrimaryKey是非必要的聚集索引,這是否準確?

+0

爲了澄清,您是否在討論如何合併包含這三個字段的非聚類非唯一索引? – 2014-10-29 17:16:17

+1

@ScottTeibert我想知道什麼更合適?包含所有三個字段的非聚集唯一索引,或僅包含兩個字段(QualifierA和QualifierB)但包含PrimaryKey的非聚集非唯一索引。 – 2014-10-29 17:31:20

+1

@FrumRoll - 所有3個場景都覆蓋了索引,但是由於RowIdentifier只會包含在葉級別,所以場景C的索引會更小。你是正確的,如果主鍵被聚集,那麼QualifierA和QualifierB上的索引將被覆蓋。 – 2014-11-11 17:23:36

回答

1

如果有一個CLUSTERED索引,它會自動包含在該表的所有索引中。你可以明確地包含它,但它不是必需的。

UNIQUE索引只是強制唯一性。 PK應該已經有了這個限制。您無需在每個索引中重新執行它。

如果你在你的where子句中包含PK,它幾乎肯定會使用PK索引來查找該行,因爲它保證返回最少的結果,因此包括在你的索引中對於查找沒有任何收穫。它也可能會歪曲基數引擎,並使SQL認爲索引比實際更明顯。

基於上述原因,我會選擇選項C

CREATE NONCLUSTERED INDEX IX_Table_QualifierA 
ON [dbo].[Table] ([QualifierA],[QualifierB]) 
INCLUDE ([RowIdentifier]) 

我想無論是什麼樣聚集列中使用此。這會給你的表現,確保索引將繼續執行,無論集羣索引如何,並明確索引的用途。

0

我在想什麼更合適?包含所有三個字段的非羣集唯一索引,或僅包含兩個字段(QualifierA & QualifierB)但包含PrimaryKey的非羣集非唯一索引。

還有第三種選擇。包含所有三個字段的非聚集,非唯一索引。

製作索引時,索引中的字段會複製到內存中的其他位置,以便服務器可以輕鬆地在這些字段後面進行操作。如果您在索引中只有QualiferA和Qualifier B,它會在該索引中找到符合條件的行,然後返回主表以獲取RowIdentifier。相反,包括所有三個以提高性能。

請記住,請確保您將RowIdentifier之前的QualifierA和QualifierB放入您的索引中。列的順序決定了數據的排序方式。

如果您願意,可以試試一下測試數據,然後查看查詢計劃,看看它在做什麼。

+0

我已經提供了額外的說明,看起來你是在方案B中提倡方案A.爲什麼UNIQUE約束會引入不必要的開銷?同樣以A或B的哪種方式優於C? – 2014-10-29 19:27:38