加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.0712zz.com/)- 应用程序、AI行业应用、CDN、低代码、区块链!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

SQL Server查询卡顿?5个索引优化技巧提速3倍

发布时间:2026-11-07 08:17:27 所属栏目:MsSql教程 来源:DaWei
导读:  去年双十一,我蹲在风控中台后台查那条“用户画像实时聚合”查询——它卡在执行计划里不动弹,SSMS右下角时间跳到四十二秒,而告警钉钉已经弹出第七条。老邵端着保温杯过来站我身后,杯底磕了我显示器边框一声脆响,他嘴上

  去年双十一,我蹲在风控中台后台查那条“用户画像实时聚合”查询——它卡在执行计划里不动弹,SSMS右下角时间跳到四十二秒,而告警钉钉已经弹出第七条。老邵端着保温杯过来站我身后,杯底磕了我显示器边框一声脆响,他嘴上说“稳住”,手却直接抄起鼠标把Query Store强制清空了。这事儿真不能怪他,我们仨上周刚被运营拉着开过会,会上那个穿灰卫衣的实习生调出自己写的SP,说“加个NOLOCK就飞起来了”,说完还顺手把茶水间微波炉叮了一声热饭盒——没人拦,真没人拦。


文章配图,仅供参考

  我原以为是统计信息过期,结果更新完还是三十七秒。我盯了十五秒执行计划,箭头全往 clustered index scan 上堆,像早高峰地铁十号线西钓鱼台站那种挤法。我抓起键盘想建个覆盖索引,手刚按下去,隔壁工位小陈突然拍桌喊“操!Redis缓存击穿了!”,然后他甩开椅子跑出去找运维——椅子腿刮地板的声音拖得老长,像生锈的刀片在擦黑板。等他回来,我索引语句已经写到INCLUDE字段,但没EXECUTE,就挂着,在编辑器里泛着灰。那会儿窗外开始下雨,不是哗啦那种,是南方三月特有的、粘在玻璃上不往下流的潮气,监控大屏反光里能看见我后脑勺几缕翘起来的头发。


  第一个技巧?别信“高选择性字段放前缀”这种祖传口诀。我拿user_id和device_fingerprint联合建过三个顺序的索引,耗时分别是二十八秒、三十一秒、二十六秒——最后那个快两秒,只因为device_fingerprint列的直方图顶点恰好卡在查询参数值附近。我敢打包票:这个偏差,你跑一百次SQL Server都不见得撞对一次。那天下午我让DBA老周重启了SQL Server实例,他敲完命令顺手关掉了机房新装的除湿机,说是“电费太狠”。机柜风扇声立刻尖了八度,嗡嗡嗡震得我左手小指发麻。后来才知道,那台除湿机接地不良,电磁干扰让tempdb日志写入有毫秒级抖动——和索引半毛钱关系没有,但它确实让慢查更慢了三天。


  第二个:别碰过滤条件里带函数的字段。有回我给login_time加了个计算列login_date = CAST(login_time AS DATE),又配了个索引。上线第一小时,WAF误拦率暴涨四成,不是规则问题,是那条聚合查询的CPU突刺触发了自动限流——安全组半夜三点打电话来,电话那头背景音是咖啡机研磨豆子的咔咔声。我一边听一边用手机查文档,发现CAST(dateadd...)这种嵌套在WHERE里,执行计划连索引都懒得看了,直接上table scan。但我真没删掉那个计算列,就搁那儿,反正也没人动它。有时候留个废索引比删错一个有用的强,你懂的。


  第三个才真要命:UNION ALL之后跟ORDER BY,你还想走索引?我试过给每个子查询单独建排序索引,结果SQL Server自己合并了,全扔进Sort Operator里干等。上季度末我们改方案,把ORDER BY提到外层视图定义里,再让应用代码分页——那天收工早,外卖骑手把盒饭放在前台时,工牌上印着“饿了么-专送2087号”,我看了一眼他左耳垂上那颗小痣,忽然想起我初中同桌也有那么一颗。后来这事没再提,但DBA老周偷偷跟我说,他用数据库镜像搞了套测试环境,结果主库事务日志暴涨,差点压垮磁盘IO——他就用那套环境测了七遍索引碎片整理周期,最后一次选的是周五下午四点十三分,因为他说“那会儿监控值班的人在打哈欠”。


  第四个是陷阱:别信SSMS里那个“建议索引”的绿字提示。它建议过两次,一次是建在is_deleted + created_time上,一次是建在status_code + updated_time上——两个都建了,性能反而倒退。我翻了三天Query Store历史,发现根本问题是查询参数嗅探失效,而它假装看不见。最后我加了OPTION (RECOMPILE),慢查秒降。这时候老邵叼着根没点着的烟坐我旁边,说:“你们 Ruby 里 proc 和 lambda 都分不清,好意思教 SQL Server 怎么编译?”我说你闭嘴。他真闭嘴了,掏出手机刷抖音,视频里一只柴犬正啃路由器线缆。


  第五个最糙:把经常join的维度表主键,冗余到事实表里。比如把region_id塞进event_log表,哪怕只多占八个字节。有人喷这是反范式,可我们查“华北+iOS+登录失败”事件时,少一次hash match,就少一帧画面卡顿。去年十二月风控大屏崩过一次,就是那次JOIN没走索引,屏幕雪花状跳动了六秒,运营那边电话打进来三十七通,接电话的小吴左手攥着签字笔,笔帽早就被咬扁了,露出里头铝皮泛青的茬口。


  现在?我还在用那个冗余region_id,没删。不是不想动,是上周三晚上九点四十,我在家改存储过程,刚保存,家里电闸跳了。恢复供电后SSMS没自动重连,我手动连上去,发现那条“聚合查询”居然跑了十九秒——比以前快三倍?我反复跑了五次,平均二十一点三秒。但我不敢报备,怕他们让我复现、画流程图、做A/B测试。窗外雨停了,晾衣绳上挂着两件衬衫,一件蓝一件灰,滴水节奏完全不一样。明天我打算先去机房看看除湿机有没有重新开机。或者,干脆买包烟,学老邵那样叼着不点。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章