2013-01-21 45 views
2

比方說,我有如下表:兩列上的單個非聚集索引或每列上的單獨索引?

Table: RelationshipType 
============================================================ 
| ID (PK) | ParentID | ChildID | RelationshipType | 
============================================================ 

大多有地方ParentIDChildID選擇在個別情況:

... WHERE ParentID = @SomeID AND ChildID = @SomeOtherID 

... WHERE ParentID = @SomeID 

... WHERE ChildID = @SomeID 

有時兩者都在選擇

我想提高這些查詢的性能,但最值得注意的是前兩項。我應該創建一個非聚集索引ParentID + ChildID在一起或一個索引ParentID和另一個索引ChildID

編輯:所有這些查詢都是高度選擇性的(返回1或2條記錄)。

+0

如何有選擇性地查找個人「ParentID」或「ChildID」?無論如何,什麼是「ChildID」?這是一個鏈表而不是樹嗎? –

+0

所有這些查詢都是高度選擇性的(1或2條記錄) – davenewza

+0

在RelationshipType(ParentID)include(ChildID):D上創建非聚集索引asdf,然後使用不同順序的列創建相同的索引,並告訴我們結果:D – WKordos

回答

3

你能擺脫代理鍵ID

如果是的話,考慮創建以下:

  • 初級和{ParentID, ChildID}clustering鍵。
  • {ChildID, ParentID}上的二級索引,但在索引中也包含RelationshipType(使用關鍵字INCLUDE)。

這樣一來,您在所有3例covering指數,所以你不必付雙查找的價格(即通常需要在集羣表二級指標):

  • ... WHERE ParentID = @SomeID可以通過索引的B-Tree中的簡單查找來滿足:{ParentID, ChildID}ChildIDRelationshipType 的值可以直接從該B-Tree的找到的葉中檢索。
  • ... WHERE ChildID = @SomeID可以通過簡單的索引在B-Tree索引中滿足:{ChildID, ParentID}ParentIDRelationshipType 的值可以直接從該B-Tree的找到的葉中檢索。
  • ... WHERE ParentID = @SomeID AND ChildID = @SomeOtherID也可以被滿足。

聚集鍵是「主」 B-Tree的表,包括所有列,而不只是那些獨一無二的。

感謝INCLUDE (RelationshipType)


做與ID目前類似的東西是可能的,但需要3個指標,而不是2,他們都將是胖實現覆蓋。你必須測量以確定,但我的感覺是,這會比它的價值更麻煩。

否則,根本不要使用集羣。只需創建以下正常索引:

  • {ID} - 定期的非羣集主索引(使用NONCLUSTERED關鍵字)。
  • {ParentID} - 常規二級指標。
  • {ChildID} - 常規二級指標。

你有一個正常的堆表,因此每次訪問都需要一個索引查找+(通常)表堆訪問,但你的指標將保持苗條,提高緩存效率。

... WHERE ParentID = @SomeID AND ChildID = @SomeOtherID將需要兩個指數的目的(也可能是尋求在任{ParentID}{ChildID}指數+表堆訪問),但是這仍然是相當快的,而不是過於頻繁(如你所說)。


請在決定任何一種方式之前測量實際的數據量。

+0

優秀答案 - 非常感謝細節。需要更多upvotes。 – davenewza

1

正如你所說的查找ParentIdChildId是高度選擇性我只是去兩個單獨的指標。

SQL Server然後可以使用WHERE ParentID = @SomeID AND ChildID = @SomeOtherID的任一索引並評估匹配的一行或兩行的殘差謂詞。

我想,如果表或多或少只讀,整個數據庫適合內存,然後沒有額外的索引,它避免了查找檢索缺失的列的內存異常。

1

在某種程度上,這是不可能說什麼會給你的數據庫的最佳性能,而無需知道這些選擇的時間和頻率的頻率發生插入/更新表,但這裏是我最好的猜測:

這聽起來像ParentID,ChildID可能是你的主鍵,這是定義一個聚集索引。

這裏做的懶惰的方法是在ParentID和ChildID上創建兩個非聚集索引。但是......特別是ParentID列或任何列在您的主鍵/集羣索引中首先出現 - 如果您創建另一個非集羣ParentID索引,我真的不確定是否會獲得任何選擇權益。非聚集索引將存儲由該索引排序的表的副本,但在這種情況下,主鍵決定了表的排序,並且首先由ParentID進行排序。

所以最後,我會在ChildID上創建ParentID和ChildID的主鍵以及非聚集索引,我認爲你很好。

1

我會創造在每一列的一個非聚集索引,但包括其他列,也是的RelationshipType柱(我假設的RelationshipType是您檢索數據):

CREATE NONCLUSTERED INDEX IX_RelationshipType_ParentID 
ON 
    RelationshipType(ParentID) 
INCLUDE 
    (ChildID, RelationshipType) 
GO 

CREATE NONCLUSTERED INDEX IX_RelationshipType_ChildID 
ON 
    RelationshipType(ChildID) 
INCLUDE 
    (ChildID, RelationshipType) 
GO 

這將導致引擎能夠在索引找到條目後從索引中獲取所需的數據,而無需在將索引中的項目放入索引後返回表格。