通常,通过设置主键在SQL Server Management Studio中创建聚簇索引,但是我最近关于PK 聚簇索引(Meaning of Primary Key to Microsoft SQL Server 2008)的问题表明,不必将PK和聚簇索引设置为相等。
那么我们应该如何选择聚集索引?让我们看下面的例子:
create table Customers (ID int, ...)
create table Orders (ID int, CustomerID int)
我们通常会在两个ID列上都创建PK / CI,但我考虑过为CustomerID中的订单创建它。那是最好的选择吗?
根据The Queen of Indexing-Kimberly Tripp-她在聚集索引中寻找的主要是:
并且,如果您还可以保证:
然后,您几乎已经拥有理想的群集密钥!
在这里查看她的整个blog post here,以及关于集群键对表操作的影响的另一个非常有趣的地方:The Clustered Index Debate Continues。
诸如INT(尤其是INT IDENTITY)或可能的INT和DATETIME之类的都是理想的候选对象。出于其他原因,GUID根本不是很好的候选者-因此您可能将GUID用作PK,但不要将表聚类到表上-它会分散成碎片,导致性能下降。
CLUSTERED
索引的最佳候选者是您最经常引用记录的键。
通常,这是PRIMARY KEY
,因为它是搜索和/或FOREIGN KEY
关系中使用的。
在您的情况下,Orders.ID
很可能会参与搜索和引用,因此它是成为聚类表达式的最佳人选。
如果在CLUSTERED
上创建Orders.CustomerID
索引,则会发生以下情况:
CustomerID
不是唯一的。为确保唯一性,将向每个记录添加一个特殊的隐藏32-bit
列,称为uniquifier
。
表中的记录将根据这对列(CustomerID, uniquifier)
进行存储。
将创建Order.ID
上的辅助索引,并以(CustomerID, uniquifier)
作为记录指针。
这样的查询:
SELECT *
FROM Orders
WHERE ID = 1234567
必须进行外部操作Clustered Seek
,因为并非所有列都存储在ID
的索引中。要检索所有列,记录应首先位于群集表中。
此附加操作需要IndexDepth
和简单的Clustered Seek
一样多的页面读取,即表中记录总数的IndexDepth
良性O(log(n))
。
如果您担心群集,通常可以帮助改善数据检索。在您的示例中,您可能希望一次获取给定客户的所有记录。基于customerID的群集会将这些行保留在同一物理页面上,而不是分散在文件的多个页面中。
ROT:聚集在要显示其集合的内容上。采购订单中的订单项就是经典示例。