sql - 两列上的单个非聚集索引还是每列上的单独索引?

标签 sql sql-server sql-server-2008 tsql database-design

假设我有下表:

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

在大多数情况下,ParentIDChildID 是单独选择的:

... 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}ChildIDRelationshipType1 的值可以直接从此 B-Tree 找到的叶子中检索。
  • ... WHERE ChildID = @SomeID 可以通过在索引的 B 树中进行简单查找来满足:{ChildID, ParentID}ParentIDRelationshipType2 的值可以直接从此 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/

相关文章:

javascript - 按名称搜索用户的最佳方法是什么?

c++ - 如何检测终止进程事​​件、计算机关闭和计算机崩溃

sql喜欢和之间

javascript - 有关更改排队/后端数据库更新的文本

sql-server - 自动从 2005 数据库同步 sql server 2008 数据库的好方法是什么?

java - 从繁忙的 Java Web 应用程序插入 30,000 个用户后,SQL Server 2008 变慢

mysql - 如何在mysql中选择每列的前3个值

sql - 如何获取该月的最后一天 (SQL Server)

php - SQLSTATE[23000] : Integrity constraint violation: 1452 Cannot add or update a child row:a foreign key

sql - 如果 SQL 中的值重复,如何使 select 语句返回 "NULLs"