我最近得到的建议是,我应该使用堆索引转换所有表,以便每个表都有一个聚簇索引。 坚持这一策略有什么后果?例如。定期重组数据库更重要吗? datagrowth?插入真的很慢的危险?如果PK是GUID,页面碎片整理的危险? 我的申请速度明显增加? 您有什么经历?
为了获得良好答案的灵感,以下是我在stackoverflow上从其他线程中获取的一些“事实”
答案 0 :(得分:9)
如果您的密钥是GUID,那么其上的非聚集索引可能与其上的聚簇索引一样有效。这是因为在GUID上你绝对不可能对它们进行范围扫描(between 'b4e8e994-c315-49c5-bbc1-f0e1b000ad7c' and '3cd22676-dffe-4152-9aef-54a6a18d32ac'
可能意味着什么?)。宽度为16个字节,GUID聚集索引键比从堆中获取的行ID宽,因此PK guid上的NC索引实际上是可以在讨论中保护的策略。
但是,使主键成为聚簇索引键而不是是在堆上构建聚簇索引的唯一方法。您是否有其他频繁查询请求超过某列的范围?典型的候选人是date
,state
或deleted
等列。如果这样做,那么您应该考虑将这些列设置为聚簇索引键(不必须是唯一的),因为这样做可能有助于查询请求范围,例如“昨天的所有记录”。 / 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树。因此,当您在同一个表上有其他索引时,它们不能指向特定行 - 而是指向聚簇索引中的“键”,因此数据的“方式”会变长。