站长速成:30分钟搞懂MSSQL核心查询
|
线上报警那一刻,我正把第三勺糖倒进咖啡里——手没抖,糖粒全落进去了,就是没搅。手机震了一下,钉钉弹出「MSSQL CPU 98%」,后面跟了个运维发来的表情包:一只猫在键盘上狂踩。我没点开,先抄起鼠标滚轮往下滑,日志里满屏是「timeout expired」,连着十二个接口,全是同一个 SP(不是存储过程,是那个叫老张写的、名叫 GetSiteConfigWithCache 的玩意儿)。 说白了,站长速成:30分钟搞懂MSSQL核心查询,这标题没骗人,真能速成。去年6月我刚接这摊子时,在测试库跑 SELECT TOP 100 FROM dbo.SiteConfig WHERE SiteId = @id,三秒。上线后查同一条,二十秒起步。我原以为是索引失效,结果发现表上压根没建非聚集索引——只有一堆 CREATE INDEX IX_XXX ON dbo.SiteConfig (SiteId) INCLUDE (ConfigJson, LastModified),建在凌晨两点,建完就忘删脚本里的 GO。谁干的?前端说不是他,产品说她只提过“配置得快”,运维反手甩来截图:建索引那行脚本,注释写着「临时应急,后续优化」——写的人头像还是灰色的,去年离职的。 窗外天黑了。我盯了三分钟执行计划,箭头又粗又红,全指着「Table Scan」,旁边还标着「Estimated Rows: 2.7 million」。其实我心里门儿清,这张表根本没做分区,也没清理历史站点,光「is_deleted=0」条件就写了五年没人动,连WHERE子句都敢用「UPPER(SiteCode) LIKE ''%ABC%''」——就为满足产品经理提的「不区分大小写搜索」,而忘了它会干掉所有索引。键盘声很响,坐我斜后方那个新来的小哥敲 F5 的节奏像心跳机,嗒、嗒、嗒……我数到第七下,突然想起他上周问我:“站长是不是管网站的?” 我点头,他认真说:“哦,那SQL算基础技能吧。” 我当时没接话,现在想,算了,基础技能,确实基础得让人脚软。 优胜劣汰这词,我原先嗤之以鼻。直到上个月灰度发布新版本,我们悄悄把老SP改成参数化查询,加了 OPTION (RECOMPILE),跑了四小时,慢查询从每分钟十七次掉到零点二三次。但你猜怎么着?不是因为写得多好,是因为旧代码里有三处地方用了 SELECT ,其中一处居然 JOIN 了 dbo.LogHistory ——一个日增五十万行、没归档、没索引、只有主键的鬼表。它被拽进来只为取一行字段叫「CreatedByUserName」,实际字段内容全是‘system’。我改掉那句,重编译,慢查没了。就这么简单。淘汰不是靠KPI,是靠它自己跑着跑着,突然卡住整个订单链路,然后凌晨三点,产品冲进群吼:“为什么下单页面白屏三分钟?!”——她说完就把会议链接发进来了,镜头里她正啃着煎饼果子,酱多得滴到笔记本键盘上。 工单系统又弹了条消息,标着「紧急」,内容是「请协助确认站点A是否已启用SSL」。我滑动鼠标滚轮,切到浏览器,搜「站点A SSL 状态」,跳出来的却是去年我写的wiki页,标题叫《站长自查清单v1.2》,最后更新时间是去年11月17号。我点开,里面第一条就写着「检查 sys.dm_exec_sessions 中 login_time 是否超48小时」,但下面小字备注:「此法仅适用于测试环境;生产库因审计策略无法启sys.dm_类视图」。我笑了。原来我早知道,但一直没修——因为修了也没人看。就像那个「CREATE PROCEDURE sp_GetConfigByDomain」,命名看着规范,可内部写了段游标遍历三百多个子域名,就为凑一个「默认配置fallback逻辑」。我查过,这游标从来没被执行过。谁写的?文档里签的是老李。老李现在在杭州做小程序外包,上个月还在朋友圈晒孩子乐高作品,底下一串点赞,没一个是我。 其实最绝的是那个 ORDER BY NEWID() 写法。有人在分页场景里直接用它随机抽三条配置推荐,说「用户体验好」。可它每次执行都重排全表,而且 MSSQL 每次都会生成全新 GUID 并排序——你猜这个表数据量?没细看,反正我看 execution plan 时看到 Memory Grant 占了整页的四分之三。我说这不行,同事问:“那换 TABLESAMPLE?” 我一愣,心想这倒是个思路……但转头看见产品在群里艾特我三次,说「推荐位今晚必须上线」,我就点了“同意合并”。现在想想,真要深究,TABLESAMPLE 也未必稳,它返回的行数浮动太大,上次AB测漏掉了某类老用户特征,导致转化率差了两个百分点——不过那不是我的事,那是数据分析组追着PM跑的事。我管不到那儿。
文章配图,仅供参考 所以别信什么「深度优化指南」,也别听那些吹「SQL调优是艺术」的。这玩意儿就跟改缓存过期时间一样,改对了省一半服务器,改错了——呵,缓存雪崩你扛,SQL雪崩我扛,谁也不比谁高贵。站长速成,说的就是你能用三十分钟,把最常触发报警的五类语句摸透:带函数的WHERE、没索引的JOIN、SELECT 加ORDER BY、游标遍历、还有那种在IN子句里塞了二百个ID还硬套子查询的憨批写法。其它?随缘。系统明天会不会崩?不知道。数据库能不能扛住大促?没细看。但我今早删掉了那个「临时应急」索引,重新建了个带过滤条件的,WHERE IsDeleted = 0 AND IsActive = 1。建完,执行计划里红色箭头淡了一半。我截图发给运维,他回了个OK手势。我现在要做的,是去查下 sys.dm_db_missing_index_details,看看还有几个「建议索引」在裸奔——或者干脆翻翻上个月离职同事的Git提交记录,找找他藏在哪次merge里的另一个sp,名字起得特别端庄:usp_SiteHealthMonitor_V2_Final。(编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |

