Car*_*ngo 5 sql sql-server indexing clustered-index
我最近得到了建议,我应该使用堆索引转换所有表,以便每个表都有一个聚簇索引.坚持这一战略会产生什么后果?例如,定期重组数据库更重要吗?datagrowth?插入真的很慢的危险?如果PK是GUID,页面碎片整理的危险?我的申请速度明显增加了吗? 你有什么经历?
为了获得良好答案的灵感,以下是我在stackoverflow上从其他线程中获取的一些"事实"
如果您的密钥是GUID,那么其上的非聚集索引可能与其上的聚簇索引一样有效.这是因为在GUID上你绝对不能对它们进行范围扫描(between 'b4e8e994-c315-49c5-bbc1-f0e1b000ad7c' and '3cd22676-dffe-4152-9aef-54a6a18d32ac'可能意味着什么?).宽度为16个字节,GUID聚集索引键比从堆中获取的行ID宽,因此PK guid上的NC索引实际上是可以在讨论中保护的策略.
但是,使主键成为聚簇索引键并不是在堆上构建聚簇索引的唯一方法.您是否有其他频繁的查询请求超过某列的范围?典型的候选人是像date,state或deleted.如果你这样做,那么你应该考虑这些列的聚集索引键(它不是必须是唯一的),因为这样做可能会帮助该请求的范围,比如"从昨天的所有记录的查询.
堆具有显着性能优势的唯一情况是插入,特别是批量插入.如果您的负载没有插入重,那么您一定要选择聚簇索引.请参阅聚集索引设计指南.
翻看你的观点:
几乎肯定希望在数据库中的每个表上建立聚簇索引.如果一张桌子没有.大多数常见查询的性能更好.
可以满足大多数查询的范围要求的聚簇索引将显着提高性能,这是真的.可以满足订单要求的聚簇索引也很有帮助,但无法满足范围要求.
GUID上的聚簇索引并不总是坏...这一切都取决于应用程序的需求.INSERT速度将受到影响,但SELECT速度将得到提高.
只有探针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给出的方案有一个更好的解决方案:解决高并发INSERT工作负载上的PAGELATCH争用,实现成本更低(需要的存储更少)并且也适用于唯一密钥(链接文章中的解决方案不适用于唯一密钥,仅适用于外国键).
群集不会影响查找速度 - 唯一的非群集索引应该可以完成工作.
对于探测器(查找特定的唯一键)是的.NC索引几乎与聚簇索引一样快(NC索引查找需要并在其余列中进行额外的键查找以获取).聚集索引闪耀的是范围扫描,因为聚簇索引可以覆盖任何查询,而可能满足相同范围的NC索引可能会在覆盖范围内松动并触发索引引爆点.