假设我有下表:
Table: RelationshipType
============================================================
| ID (PK) | ParentID | ChildID | RelationshipType |
============================================================
在大多数情况下,ParentID
和 ChildID
是单独选择的:
... WHERE ParentID = @SomeID
... WHERE ChildID = @SomeID
有时两者都被选中:
... WHERE ParentID = @SomeID AND ChildID = @SomeOtherID
我想提高这些查询的性能,但最显着的是前两个。我应该在 ParentID
+ ChildID
上同时创建一个非聚集索引,还是在 ParentID
上创建一个索引,在 ChildID
上创建另一个索引>?
编辑:所有这些查询都是高度选择性的(返回 1 或 2 条记录)。
最佳答案
你能去掉代理键ID
吗?
如果是,请考虑创建以下内容:
- A 小学和 clustering
{ParentID, ChildID}
键。 {ChildID, ParentID}
的二级索引,但也在索引中包含RelationshipType
(使用 INCLUDE 关键字)。
这样,你就有了一个covering索引在所有 3 种情况下,因此您不必支付双重查找的代价(这通常是聚簇表中的二级索引所必需的):
... WHERE ParentID = @SomeID
可以通过在索引的 B 树中进行简单查找来满足:{ParentID, ChildID}
。ChildID
和RelationshipType
1 的值可以直接从此 B-Tree 找到的叶子中检索。... WHERE ChildID = @SomeID
可以通过在索引的 B 树中进行简单查找来满足:{ChildID, ParentID}
。ParentID
和RelationshipType
2 的值可以直接从此 B 树的找到的叶子中检索。... WHERE ParentID = @SomeID AND ChildID = @SomeOtherID
两者都可以满足。
1 聚类键是表的“主要”B 树,包括所有列,而不仅仅是那些唯一的列。
2 感谢 INCLUDE (RelationshipType)
。
用存在的 ID
做一些类似的事情是可能的,但是需要 3 个索引而不是 2 个,而且所有的索引都会更胖以实现覆盖。您必须进行测量才能确定,但我的感觉是这会带来更多麻烦,而不是值得的。
否则,根本不要使用聚类。只需在以下位置创建普通索引:
{ID}
- 常规的非聚集主索引(使用 NONCLUSTERED 关键字)。{ParentID}
- 常规二级索引。{ChildID}
- 常规二级索引。
您将拥有一个普通的堆表,因此每次访问都需要一个索引查找 +(通常)表堆访问,但您的索引将保持 slim ,从而提高缓存效率。 p>
... WHERE ParentID = @SomeID AND ChildID = @SomeOtherID
将需要两次索引查找(或者可能在 {ParentID}
或 { ChildID}
index + table heap access),但这仍然非常快并且不太频繁(如您所说)。
在决定任何一种方式之前,请先衡量实际的数据量。
关于sql - 两列上的单个非聚集索引还是每列上的单独索引?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14438387/