前事不忘,后事之师,不忘国耻!

 用户注册  找回密码
 用户注册
搜索
查看: 30|回复: 0

[基础管理] SQL Server 索引深入:聚集与非聚集索引选型

[复制链接]

[基础管理] SQL Server 索引深入:聚集与非聚集索引选型

[复制链接]
dbaai

主题

0

回帖

28

积分

DBAAI

积分
28
昨天 09:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?用户注册

×
一、具体的问题

很多 DBA 一接到"查询变慢"的工单,条件反射就是加索引,但加错类型反而让写入和读取一起变慢。真正要回答的是一个具体问题:这张表到底该用聚集索引还是非聚集索引,聚集键又该选哪一列?

二、核心原理

1. 两种索引的本质区别

聚集索引决定数据行的物理存储顺序,一张表只能有一个,它本身就是数据;非聚集索引是另一棵独立的 B 树,叶子节点存的是"行定位符"(聚集键或行标识符),靠它再回到数据页取其余列。正因如此,把错误的列当聚集键,会直接引发页分裂和写入放大。

2. 选型的核心原则:窄、唯一、静态、递增

最理想的是用整数或长整数加自增属性,或者"日期加自增"这类单调增长的列;它让新数据总是追加到表尾,几乎不产生页分裂。非聚集索引用来服务高频的过滤、连接和排序列,但要注意"键查找"陷阱:如果查询还要取不在索引键里的列,数据库就得用定位符回表,一次查询可能多出成百上千次随机 IO。解决办法是把常用输出列包进索引叶子做成"覆盖索引",从而避免回表。

3. 一个常见的翻车现场

一张高频写入的订单表,主键用随机生成的全局唯一标识符,并且被设成了聚集索引。随机值会让新记录的聚集键散落到各个数据页,几乎每次插入都触发页分裂,过不了多久索引碎片就能到 90% 以上;查询也因为随机 IO 变得很慢。这就是典型的选错类型。

提示:索引不是越多越好。曾有人给一张日志表建了 7 个非聚集索引,写入吞吐掉了快一半,因为每次落库都要维护 7 棵树。正确做法是用索引使用统计动态视图找出从未被使用的索引果断删除,对高碎片索引定期重建或重组。

三、实例参考(动手步骤)

下面以订单表从"随机聚集键"改造为"自增聚集键加覆盖非聚集索引"为例,给出可照做的步骤。

1) 先看现状:查一下该表已有的索引清单与每个索引的类型、填充因子,并用索引物理统计动态视图看碎片率和碎片数,确认是否真的很高。

2) 新增一列长整数自增字段作为新的聚集键,并把这一列设为唯一聚集索引,替换掉原来那个随机聚集键。这一步会把数据重排成按新键顺序存储。

3) 为"按客户查订单"的高频查询建一个覆盖非聚集索引:索引键用客户编号,把订单日期和状态这两个常用输出列放进包含列,这样查询就不需要再回表。

4) 验证:打开执行计划看是否还有键查找(应消失),并用逻辑读对比改造前后——同样一条按客户查订单的语句,逻辑读应显著下降。

5) 收尾对比:把聚集键从随机改成递增后,再次跑第 1 步的碎片语句,碎片数应明显下降,插入也不再频繁页分裂。

四、实操检查清单

- 聚集索引键是否为"窄、唯一、静态、递增"的列(如自增整数),而非随机全局唯一标识符?
- 单表是否只保留一个聚集索引,且其键值不会频繁更新?
- 非聚集索引是否只服务真实高频的过滤、连接、排序列,而不是想到就建?
- 高频查询的回表是否被覆盖索引消除(检查执行计划里的键查找)?
- 是否用索引使用统计动态视图定期清理零使用率的索引,避免写入为维护索引买单?
- 高碎片索引是否按阈值选择重建或重组,而不是长期放任?
免责申明1、欢迎访问本站,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@dbabbs.com
您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

QQ|Archiver|小黑屋|DBA论坛中国 ( 鲁ICP备20017503号-2 )

GMT+8, 2026-8-15 03:20 , Processed in 0.014732 second(s), 9 queries , MemCached On.

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表