SQL Server查询卡顿?5个索引优化技巧提速3倍
|
掘金这标题我扫到第三遍才点进去——不是因为不信,是去年四月在宝山机房蹲着听SQL Server查订单表卡成PPT时,隔壁运维老张正往散热口塞冰可乐罐,铝罐底朝外,嘶嘶冒气,像台快报废的ATX电源。我敢打包票那会儿IO等待时间飘到四百多毫秒,但具体数字?我说不准,监控面板右下角时间戳跳得歪歪扭扭,跟人抽筋似的。
文章配图,仅供参考 踩坑复盘。就那个查用户积分流水的视图,没加WHERE直接SELECT TOP 100,跑了十八秒。DBA小王当时正用手机拍屏幕录像,镜头抖得厉害,左上角还反光出他后颈上一块膏药——贴歪了,翘起个角。我原以为是统计信息过期,结果更新完照样卡。后来发现执行计划里赫然两个Nested Loops,一个连着非聚集索引查找,另一个……连着另一张表的聚集索引扫描,而那张表根本没建任何索引,只有主键约束。主键还是GUID。对,就是那种insert一单就碎一次页的那种。 第一个技巧?别他妈瞎建覆盖索引。上周三我见人给订单主表建了个包含十五列的INCLUDE索引,美其名曰“一步到位”。我问:“你SELECT里真用全这十五个?”他眨眨眼,说“可能以后会用”。可能。这个词我听了十年。结果昨天他们报表库又崩了——索引大小比表数据还大两倍,维护窗口全耗在索引重组上,日志切都切不动。优胜劣汰?对,淘汰的就是这种“可能以后”的索引。淘汰得干净利落。 第二个:删掉那些凌晨两点自动重建的索引任务。真·自毁式运维。我们上个月把job停了,用sp_BlitzIndex跑了一次,揪出来七个重复索引——其中三个字段顺序不同但列集合完全一致,第四个甚至只是第三个加了个INCLUDE,而INCLUDE的列在SELECT里压根没出现过。李工当时蹲在机柜旁接电话,左手捏着耳机线绕了三圈,右手无意识敲着膝盖,频率和服务器风扇声差不多。他说:“反正业务没告警。”可告警不等于没杀伤力啊,磁盘队列长度已经稳在八以上了,只是没人看历史趋势图。 第三个技巧?把书签查找(Key Lookup)当红灯。不是所有都是病,但看到Clustered Index Seek + Key Lookup配对出现三次以上,就该拎桶水泼醒自己。我们有个支付状态同步作业,每天凌晨触发,执行计划里Lookup占总成本六成二。我让小王把它改成了Covering Index,加了status_code和updated_at两个INCLUDE列——他改完发邮件抄送我,主题写“已修”,正文空着。我回了个句号。结果第二天监控报警说tempdb增长异常,一看——他 INCLUDE 里手抖多敲了个逗号,SQL Server把它解析成字符串字面量,于是整张索引变成非压缩状态。三百七十二GB临时文件,撑爆LUN。我原以为是他语法错了,结果是SSMS编辑器的自动补全在捣鬼,它默认在括号后加空格加逗号……这玩意儿我调过七次配置都没关掉。 第四个:别信统计信息“自动更新”。我们线上数据库设的是auto_update_statistics_async = ON。听着很乖是吧?结果某天下午查一个三年前的老会员积分变更记录,执行计划硬生生选错索引——因为统计信息最后更新时间是去年十一月,而那位会员恰好是在今年二月最后一次活跃。我盯着sys.dm_db_stats_properties查出来的modification_counter值看了半分钟,数值是十七。十七。十七次DML就能触发异步更新?不,它等的是百分之二十的行变更量。而这张表五千万行,百分之二十是整整一千万。谁等得起?窗外正好打雷,机房空调突然停了十秒,UPS报警声短促地“嘀”了一声,像在嘲笑。 第五个,也是最反常识的:有时候删索引比建索引更快。去年四月那个订单表,我们干掉四个低频查询用的冗余索引后,整体写入吞吐涨了——不是查得快了,是写入阻塞少了。因为原先每次INSERT都要刷五个索引页进buffer pool,现在只要刷一个。你问我测了多久?两天。第一天空跑,第二天天没亮我就盯着Performance Monitor的Page Life Expectancy曲线——它从平均六十八秒爬到了一百零三秒。但我说不准这个提升是不是和那天晚上的网络抖动有关,因为同一时段AD域验证延迟也变长了,老张边喝豆浆边说“肯定又是微软补丁搞的鬼”,豆浆渣粘在他右嘴角,没擦。 讲个跑题的:前天看见个脚本,用sp_MSforeachtable遍历所有表,对每个主键列跑DBCC SHOW_STATISTICS,再用REPLACE把histogram里所有“RANGE_HI_KEY”后面的时间戳全替换成GETDATE()……这玩意儿是哪个实习生写的?我让他来找我,他抱着MacBook Air进来,键盘膜上贴着一张卡通猫贴纸,右下角翘起来。我没吭声,就指了指他屏幕上那行“— DO NOT RUN IN PROD”。他赶紧关掉了。但你知道最绝的是什么吗?他改的不是测试库,是他自己本地SQL Server Express实例——因为怕被发现,特意在虚拟机里装了个干净系统。结果那台VM硬盘IOPS爆了,把宿主机的vMotion全卡住了。我们运维组那会儿还在排查vmkernel日志里的警告,谁也没想到源头是台贴着卡通猫的笔记本。 提速三倍这事,站得住脚的地方就一个:优胜劣汰。不是技术赢了,是活下来的索引更懂收敛。剩下那些,要么死在自动统计更新的幻觉里,要么卡在GUID主键的碎片中,要么糊在INCLUDE列的手抖上。我现在写完索引脚本必做两件事:先DROP_EXISTING=ON,再跑一遍SET STATISTICS XML ON手动核对。不是信不过SQL Server,是信不过自己昨晚是不是又忘了关VS Code的自动格式化插件。下周我打算去趟宝山机房,带盒薄荷糖——上次老张说他含着能提神,我不信,但想试试。可我不知道他今天还贴不贴膏药。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |




