87

如果聚集索引不是唯一的会发生什么?它会因为插入的行流向某种“溢出”页面而导致性能下降吗?

它是“制造”独特的吗?如果是,如何?让它独一无二的最佳方法是什么?

我之所以问是因为我目前正在使用聚集索引将表划分为逻辑部分,但性能一般,最近我得到了使聚集索引唯一的建议。我想对此发表第二意见。

4

3 回答 3

96

They don't have to be unique but it certainly is encouraged.
I haven't encountered a scenario yet where I wanted to create a CI on a non-unique column.

What happens if you create a CI on a non-unique column

If the clustered index is not a unique index, SQL Server makes any duplicate keys unique by adding an internally generated value called a uniqueifier

Does this lead to bad performance?

Adding a uniqueifier certainly adds some overhead in calculating and in storing it.
If this overhead will be noticable depends on several factors.

  • How much data the table contains.
  • What is the rate of inserts.
  • How often is the CI used in a select (when no covering indexes exist, pretty much always).

Edit
as been pointed out by Remus in comments, there do exist use cases where creating a non-unique CI would be a reasonable choice. Me not having encountered one off those scenarios merely shows my own lack of exposure or competence (pick your choice).

于 2010-12-02T08:25:27.630 回答
32

我想看看索引女王金伯利·特里普 (Kimberly Tripp) 对这个话题的看法:

我将从我对 Clustering Key 的建议开始 - 有几个原因。首先,这是一个容易做出的决定,其次,尽早做出这个决定有助于主动防止某些类型的碎片化。如果您可以防止某些类型的基表碎片,那么您可以最大限度地减少一些维护活动(其中一些在 SQL Server 2000 中,而在 SQL Server 2005 中则更少)要求您的表处于脱机状态。好的,我稍后会去重建的东西......

让我们从我在集群键中寻找的关键内容开始:

* Unique
* Narrow
* Static

为什么是独一无二的? 集群键应该是唯一的,因为集群键(如果存在)被用作所有非聚集索引的查找键。以书后的索引为例 - 如果您需要查找索引条目指向的数据 - 该条目(索引条目)必须是唯一的,否则,哪个索引条目将是您要查找的条目? 因此,当您创建聚集索引时 - 它必须是唯一的。但是,SQL Server 不需要在唯一列上创建您的集群键。您可以在任何您想要的列上创建它。在内部,如果集群键不是唯一的,那么 SQL Server 将通过向数据添加一个 4 字节整数来“唯一化”它。因此,如果聚集索引是在不唯一的东西上创建的,那么不仅在创建索引时会有额外的开销,还会浪费磁盘空间,

资料来源: 不断增加的聚类关键辩论 - 再次!

于 2010-12-02T09:19:13.977 回答
9

聚集索引必须是唯一的吗?

他们不这样做,有时如果他们不这样做会更好。

考虑一个具有半随机、唯一 EmployeeId 和每个员工的 DepartmentId 的表:如果您的 select 语句是

SELECT * FROM EmployeeTable WHERE DepartmentId=%DepartmentValue%

如果它是聚集索引,那么它对性能最好,DepartmentId即使(甚至特别是因为)它不是唯一索引(对性能最好,因为它确保给定 DepartmentId 中的所有记录都是聚集的)。


你有参考吗?

例如,有聚集索引设计指南,它说,

除了少数例外,每个表都应该在列上定义一个聚集索引,或者列,提供以下内容:

  • 可用于经常使用的查询。
  • 提供高度的独特性。
  • 可用于范围查询。

例如,我对“高度唯一性”的理解是,如果您的大多数查询都想选择给定城镇内的记录,那么选择“国家”作为聚集索引是不好的。

于 2010-12-02T08:48:36.257 回答