加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.0516zz.com/)- 智能数字人、图像技术、AI硬件、数据标注、数据治理!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MySQL慢查询优化实战:1年实习的毫秒级突破

发布时间:2026-10-15 11:17:28 所属栏目:MySql教程 来源:DaWei
导读:  去年寒假,我蹲在机房三排最里头那台灰壳Dell上改索引,空调冷凝水正一滴一滴砸在主机箱侧面——叮、叮、叮。那个节奏比explain输出还准。老张端着保温杯从我背后路过,杯盖没拧紧,一颠一晃地漏茶渍,蹭在我显示器边框上,

  去年寒假,我蹲在机房三排最里头那台灰壳Dell上改索引,空调冷凝水正一滴一滴砸在主机箱侧面——叮、叮、叮。那个节奏比explain输出还准。老张端着保温杯从我背后路过,杯盖没拧紧,一颠一晃地漏茶渍,蹭在我显示器边框上,像条浅褐色的蚯蚓。


  不是我说,慢查优化这事儿,压根不是技术题,是生态题。优胜劣汰。你加个联合索引,跑通了;隔壁组死磕hint,把optimizer搞出应激反应;运维小哥默默把slow_log阈值调成三百七十二毫秒,然后截图发群说“已收敛”。没人验收对错,只看谁先不告警。我原以为得背完整本《高性能MySQL》第几章才能动alter table,结果?删了条没用的order by,查询从卡顿直接跳成“咦?它跑了?”


  那天下午四点二十三分,DBA老李接了个电话,左手举着听筒,右手在白板上画了个歪掉的B+树,粉笔断了两次。他最后说:“你这个where里嵌套子查询再套函数,它连统计信息都懒得采。”我没吱声,但手已经切到navicat敲drop index idx_user_status_on_created_time on user_order。删完回车,还没等我咽下嘴里的凉皮,监控图就往下栽了一截——不是平滑下降,是像被掐住脖子似的,猛地一坠。


  但真要命的是那个外键。表A有个status字段,type是tinyint,却跟表B的varchar(32) status_name外键关联。开发文档写的是“语义一致”,可MySQL runtime里,它每次join都偷偷做隐式转换,还带函数索引失效。我查show create table的时候,发现表B的status_name上居然建了fulltext索引——为一个永远只eq匹配的字段。我就问了一句:“这索引用在哪了?”没人回答。工位对面的实习生小陈抬头看了我一眼,低头继续敲单元测试,筷子还插在他午饭剩的咖喱鸡块里,没拔出来。


文章配图,仅供参考

  有次我把order by改成覆盖索引,explain显示Using index,结果响应时间反而涨了八秒。我盯着执行计划看了四十分钟,直到窗外天色发青。后来才发现,是buffer_pool被某个凌晨跑的备份脚本吃掉了七成,缓存命中率掉到百分之二十几。这不是SQL的问题,是人在调度时忘了自己是个节点。我敢打包票:那晚机房UPS报警灯闪了三次红光,每次间隔正好是十四秒——不是整数,是十四、十四、十四。但你说这跟优化有没有关系?我说不准。


  我们组周五例行复盘,产品经理抱着iPad进来,说“用户反馈列表加载太慢”。后端老大点头,说“下周排期加个缓存”。没人提那句“WHERE created_at > DATE_SUB(NOW(), INTERVAL 7 DAY) AND user_id IN (SELECT id FROM user WHERE role = 'vip')”已经在执行计划里裸奔了三个月。我就坐在那儿啃半块苹果,果核扔进桌角奶茶杯,糖浆黏住了三颗籽。旁边打印机突然开始吐纸,不是我们提交的,是测试环境自动跑的全量数据校验日志——A4纸堆起来有四厘米高,边缘都卷边了。


  最离谱的是那个日期函数。业务方坚持用DATE(created_at),我说换成created_at >= '2024-01-15' and created_at < '2024-01-16'试试?他们反问我:“那节假日补班怎么办?”——可这张表根本没节假日字段啊。我当场愣住,手停在键盘上,食指悬在回车键上方两毫米。窗外雨突然变大,雨刷器节奏乱了,左快右慢,嗒、嗒嗒、嗒。后来我悄悄在dev分支把DATE()全替了,没提PR,上线后查日志,QPS峰值纹丝不动,但p99毛刺没了。就像抽掉一根扎进肉里的细刺,你不喊疼,但走路突然轻松了。


  其实现在看,很多优化不是“改对了”,是“侥幸没塌”。比如那个复合索引我建了(user_id, status, created_at),可第二天业务加了个新过滤条件region_code,又跪了。不是设计不好,是需求比索引长得快。我原以为得把所有字段排列组合试一遍,结果上线前夜,运维顺手把innodb_buffer_pool_size从8G调到12G,慢查报表当天清零——不是我的功劳,是我运气比buffer_pool热得早。


  上个月我路过DBA工位,看见老李电脑屏保是张Excel截图,里面密密麻麻标着红黄绿:绿色是“索引可用”,黄色是“函数导致失效”,红色是“请重写SQL”。第三列写着“负责人”,我名字后面打了个问号。他抬头瞥我一眼,没说话,伸手按了按鼠标,屏保熄了。桌上外卖盒盖掀开一条缝,露出底下没动过的葱油饼,边沿已经硬成浅褐色的壳。


  我打算下周去翻下performance_schema里最近一周的statement_analysis,挑三条最常超时的SQL,挨个跑一遍optimizer_trace。不一定能改完,但得看看MySQL到底在它自己脑子里,把我的SQL翻译成了什么鬼话。

(编辑:站长网)

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