如何在SQL Server中选择聚簇索引?

问题描述 投票:11回答:3

通常,通过设置主键在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中的订单创建它。那是最好的选择吗?

sql-server database-design sql-server-2008 primary-key clustered-index
3个回答
13
投票

根据The Queen of Indexing-Kimberly Tripp-她在聚集索引中寻找的主要是:

  • 唯一
  • 静态

并且,如果您还可以保证:

  • 不断增加的模式

然后,您几乎已经拥有理想的群集密钥!

在这里查看她的整个blog post here,以及关于集群键对表操作的影响的另一个非常有趣的地方:The Clustered Index Debate Continues

诸如INT(尤其是INT IDENTITY)或可能的INT和DATETIME之类的都是理想的候选对象。出于其他原因,GUID根本不是很好的候选者-因此您可能将GUID用作PK,但不要将表聚类到表上-它会分散成碎片,导致性能下降。


6
投票

CLUSTERED索引的最佳候选者是您最经常引用记录的键。

通常,这是PRIMARY KEY,因为它是搜索和/或FOREIGN KEY关系中使用的。

在您的情况下,Orders.ID很可能会参与搜索和引用,因此它是成为聚类表达式的最佳人选。

如果在CLUSTERED上创建Orders.CustomerID索引,则会发生以下情况:

  1. CustomerID不是唯一的。为确保唯一性,将向每个记录添加一个特殊的隐藏32-bit列,称为uniquifier

  2. 表中的记录将根据这对列(CustomerID, uniquifier)进行存储。

  3. 将创建Order.ID上的辅助索引,并以(CustomerID, uniquifier)作为记录指针。

  4. 这样的查询:

    SELECT  *
    FROM    Orders
    WHERE   ID = 1234567
    

    必须进行外部操作Clustered Seek,因为并非所有列都存储在ID的索引中。要检索所有列,记录应首先位于群集表中。

此附加操作需要IndexDepth和简单的Clustered Seek一样多的页面读取,即表中记录总数的IndexDepth良性O(log(n))


1
投票

如果您担心群集,通常可以帮助改善数据检索。在您的示例中,您可能希望一次获取给定客户的所有记录。基于customerID的群集会将这些行保留在同一物理页面上,而不是分散在文件的多个页面中。

ROT:聚集在要显示其集合的内容上。采购订单中的订单项就是经典示例。

© www.soinside.com 2019 - 2024. All rights reserved.