2013-01-21 43 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 

这将导致引擎能够在索引找到条目后从索引中获取所需的数据,而无需在将索引中的项目放入索引后返回表格。