【问题标题】:How to choose the clustered index in SQL Server?SQL Server 中如何选择聚集索引?
【发布时间】:2011-01-17 01:29:30
【问题描述】:

通常通过设置主键在 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


【解决方案1】:

根据索引女王 - Kimberly Tripp - 她在聚集索引中寻找的主要内容是:

  • 独特
  • 静态

如果你还可以保证:

  • 不断增长的模式

那么您就非常接近拥有理想的集群密钥了!

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

任何像 INT(尤其是 INT IDENTITY)或可能是 INT 和 DATETIME 的东西都是理想的候选对象。由于其他原因,GUID 根本不是很好的候选者 - 所以您可能将 GUID 作为您的 PK,但不要将您的表聚集在它上面 - 它会碎片化而无法识别,并且性能会受到影响。

【讨论】:

  • 这些博客文章是否仍然与较新版本的 SQL Server 相关,或者最近在 SQL Server 2008 中进行了性能调整,后来以某种方式改变了最佳实践?
  • @AdrianGrigore:一切仍然有效,只要您使用“普通”表(例如,不是数据仓库/列存储的东西)
  • @marc_s 感谢您的指导,我也阅读了 Kimberly 的文章,我很困惑,希望您能帮助我,她说可以将 guid 与默认的 sequenceId() 一起使用,而您说他们根本不是好的候选人,我想知道我的表上没有聚集索引或顺序 guid 上没有聚集索引,
  • @Mostafa:Guid 总是很糟糕,因为它们太大了(是 bigint 的两倍,是 int 的四倍)。使用newsequentialid(),至少它们不是完全随机的——它比newid()更好,但它仍然比intbigint 差。如果您出于任何原因必须使用 guid,则确保使用 newsequentialid() 作为该列的默认子句。但是,如果可以的话 - 完全避免将 guid 作为集群键
  • 我想说最大的问题是碎片化甚至超过了大小。
【解决方案2】:

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

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

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

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

  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 一样多的页面读取,IndexDepthO(log(n)) 表中的记录总数。

【讨论】:

    【解决方案3】:

    如果您担心聚类,通常是为了帮助改进数据检索。在您的示例中,您可能希望一次获得给定客户的所有记录。对 customerID 进行聚类将使这些行保持在同一个物理页面上,而不是分散在文件中的多个页面中。

    ROT:在您要显示的集合上进行聚类。采购订单中的订单项就是典型的例子。

    【讨论】:

    • 订单上的订单项对于集群来说可能是个好主意,但如果典型订单上只有 2 或 3 个(或十几个)订单项,则不是。除非您聚集在一起的行开始达到数十或数百,否则最好让 SQL Server 执行书签查找。我有一个系统,业务需求必须找到在特定收银员轮班期间发生的所有“行项目”(以查看它们是否平衡)。如果 Shift 使用 id 对“行项目”进行非规范化,然后在 Shift 上进行聚类,可以大大提高速度。
    猜你喜欢
    • 1970-01-01
    • 2014-12-21
    • 2018-05-08
    • 2012-10-01
    • 2013-08-20
    • 2011-01-13
    • 2012-02-02
    • 2010-11-23
    相关资源
    最近更新 更多