在SQL Server上将堆索引转换为聚簇索引会产生什么后果?

时间:2010-12-13 21:22:36

标签: sql sql-server indexing clustered-index

我最近得到的建议是,我应该使用堆索引转换所有表,以便每个表都有一个聚簇索引。 坚持这一策略有什么后果?例如。定期重组数据库更重要吗? datagrowth?插入真的很慢的危险?如果PK是GUID,页面碎片整理的危险? 我的申请速度明显增加? 您有什么经历?

为了获得良好答案的灵感,以下是我在stackoverflow上从其他线程中获取的一些“事实”

  1. 几乎肯定希望在数据库中的每个表上建立聚簇索引。如果一张桌子没有。最常见的查询的表现更好。
  2. 群集索引在GUID上并不总是坏...这一切都取决于您的应用程序的需求。 INSERT速度会受到影响,但SELECT速度会有所提高。
  3. GUID字段中聚簇索引的问题是GUID是随机的,因此当插入新记录时,必须移动磁盘上的大部分数据以将记录插入表的中间。
  4. GUID上的聚簇索引在GUID具有意义的情况下是可以的,并通过将相关数据放在彼此附近来提高性能http://randommadness.blogspot.com/2008/07/guids-and-clustered-indexes.html
  5. 群集不会影响查找速度 - 唯一的非群集索引应该可以完成工作。

3 个答案:

答案 0 :(得分:9)

如果您的密钥是GUID,那么其上的非聚集索引可能与其上的聚簇索引一样有效。这是因为在GUID上你绝对不可能对它们进行范围扫描(between 'b4e8e994-c315-49c5-bbc1-f0e1b000ad7c' and '3cd22676-dffe-4152-9aef-54a6a18d32ac'可能意味着什么?)。宽度为16个字节,GUID聚集索引键比从堆中获取的行ID宽,因此PK guid上的NC索引实际上是可以在讨论中保护的策略。

但是,使主键成为聚簇索引键而不是是在堆上构建聚簇索引的唯一方法。您是否有其他频繁查询请求超过某列的范围?典型的候选人是datestatedeleted等列。如果这样做,那么您应该考虑将这些列设置为聚簇索引键(必须是唯一的),因为这样做可能有助于查询请求范围,例如“昨天的所有记录”。 / p>

堆具有显着性能优势的唯一方案是插入,特别是批量插入。如果您的负载没有插入重,那么您一定要选择聚簇索引。请参阅Clustered Index Design Guidelines

完成你的观点:

  

几乎可以肯定想在每个表上建立一个聚簇索引   你的数据库。如果表没有   有一个。性能最常见   查询更好。

可以满足大多数查询的范围要求的聚簇索引将显着提高性能,这是真的。可以满足订单要求的聚集索引也很有帮助,但无法满足范围要求。

  

群集索引在GUID上并不总是坏...这一切都取决于   您的应用程序的需求。该   INSERT速度会受到影响,但是   选择速度将得到提高。

只会改进探测SELECT:SELECT ... WHERE key='someguid';。按对象ID和外键查找进行的查询将受益于此聚簇索引。 NC索引也可以用于同样的目的。

  

GUID字段中聚簇索引的问题是GUID   随机的,所以当一个新的记录是   插入,很大一部分   磁盘上的数据必须移动到插入   记录进入中间   表

错误。插入到索引中的位置必须移动数据。可能发生的最糟糕的事情是页面拆分。 Page-split(以某种方式)是昂贵的,但不是世界末日。您的评论建议必须移动所有数据(或至少是“重要”部分)为新行腾出空间,这远不是真的。

  

GUID上的聚簇索引在GUID具有的情况下是可以的   意义和提高性能   将相关数据放在每个附近   其他   http://randommadness.blogspot.com/2008/07/guids-and-clustered-indexes.html

我无法想象GUID可以拥有“相关数据”的场景。 GUID是典型的随机结构,两个随机GUID如何以任何方式相关联? Donald给出的方案有一个更好的解决方案:Resolving PAGELATCH Contention on Highly Concurrent INSERT Workloads,实现成本更低(需要更少的存储空间)并且也适用于唯一键(链接文章中的解决方案不适用于唯一键,仅适用于外键)。

  

群集不会影响查找速度 - 唯一的非群集索引   应该做的。

对于探测器(查找特定的唯一键)是。 NC索引几乎与聚簇索引一样快(NC索引查找 需要并且其他键查找以在其余列中获取)。聚集索引闪耀的是范围扫描,因为聚簇索引可以覆盖任何查询,而 可能可能满足相同范围的NC索引可能会在上松散覆盖并触发Index Tipping Point

答案 1 :(得分:2)

我还建议您阅读Kimberly Tripp的The Clustered Index Debate Continues...,其中详细说明了使用* 良好的群集密钥而不是拥有堆的所有好处。

几乎所有操作都更快 - 是!甚至插入和更新!

但这需要良好群集密钥,并且具有非常随机和不可预测性质的GUID不被视为群集密钥的良好候选者。作为集群密钥的GUID很糟糕 - 无论它们是否具有应用程序含义 - 只需避免使用它们。

你最好的选择是一个狭窄,稳定,独特且不断增加的关键 - INT IDENTITY类型的列理想地满足所有这些要求。

关于为什么GUID没有成为一个好的群集密钥的更多背景,以及它有多糟糕,请参阅更多Kim Tripp的博客文章:

答案 2 :(得分:1)

我可以推荐“SQL Performance Explained”一书 - 这是一本关于索引的200页书。

它还提到了聚簇索引的性能比普通索引差。其中一个问题是聚簇索引本身就是一个B树。因此,当您在同一个表上有其他索引时,它们不能指向特定行 - 而是指向聚簇索引中的“键”,因此数据的“方式”会变长。