如果您的键是 GUID,那么它上的非聚集索引可能与它上的聚集索引一样有效。这是因为在 GUID 上,您绝对永远无法对它们进行范围扫描(between 'b4e8e994-c315-49c5-bbc1-f0e1b000ad7c' and '3cd22676-dffe-4152-9aef-54a6a18d32ac'
可能意味着什么??)。GUID 聚集索引键的宽度为 16 字节,比您从堆中获得的行 ID 更宽,因此 PK GUID 上的 NC 索引实际上是可以在讨论中进行辩护的策略。
但是使主键成为聚集索引键并不是在堆上构建聚集索引的唯一方法。您是否有其他频繁查询请求某个列的范围?典型的候选者是date
,state
或之类的列deleted
。如果这样做,那么您应该考虑将这些列设置为聚集索引键(它不必是唯一的),因为这样做可能有助于查询请求范围,例如“昨天的所有记录”。
堆具有显着性能优势的唯一场景是插入,特别是批量插入。如果您的负载不是很重,那么您绝对应该使用聚集索引。请参阅聚集索引设计指南。
回顾你的观点:
几乎可以肯定要在数据库中的每个表上建立聚集索引。如果一张桌子没有。大多数常见查询的性能更好。
可以满足大多数查询的范围要求的聚集索引将显着提高性能,真的。可以满足顺序要求的聚簇索引也很有帮助,但没有一个可以满足范围的索引那么有用。
聚集索引在 GUID 上并不总是坏事……这完全取决于您的应用程序的需求。INSERT 速度会受到影响,但 SELECT 速度会有所提高。
只有探测 SELECT 会得到改进:SELECT ... WHERE key='someguid';
。按对象 ID 和外键查找的查询将受益于此聚集索引。NC 索引也可以达到同样的目的。
GUID 字段中的聚集索引的问题在于 GUID 是随机的,因此当插入新记录时,必须移动磁盘上的大部分数据才能将记录插入到表的中间。
错误的。在索引中插入位置不必移动数据。它可能发生的最坏情况是页面拆分。页面拆分(不知何故)很昂贵,但不是世界末日。您的评论建议必须移动所有数据(或至少“重要”部分)以为新行腾出空间,这远非如此。
在 GUID 有意义并通过将相关数据彼此靠近来提高性能的情况下,GUID 上的聚集索引是可以的
http://randommadness.blogspot.com/2008/07/guids-and-clustered-indexes.html
我无法想象 GUID 可以拥有“相关数据”的场景。GUID 是典型的随机结构,两个随机 GUID 如何以任何方式关联?Donald 给出的场景有一个更好的解决方案:Resolving PAGELATCH Contention on High Concurrent INSERT Workloads,实现起来更便宜(需要更少的存储空间)并且也适用于唯一键(链接文章中的解决方案不适用于唯一键,仅适用于外键键)。
集群不会影响查找速度 - 一个唯一的非聚集索引应该可以完成这项工作。
对于探测(查找特定的唯一键)是的。NC 索引几乎与聚集索引一样快(NC 索引查找确实需要额外的键查找来获取其余列)。聚集索引的亮点是范围扫描,因为聚集索引可以覆盖任何查询,而可能满足相同范围的 NC 索引可能会失去覆盖范围并触发Index Tipping Point。