14年DBA亲授:MySQL慢查询毫秒级优化实战
|
跟产品吵完第三轮,咖啡杯上那个“云帆科技”logo已经褪成浅灰色了——就印在杯沿咬痕那儿,我每天拿它蹭牙。PM举着平板说“用户等不及”,前端在隔壁工位敲键盘跟打字机似的,嗒嗒嗒,每声都卡在我太阳穴上。我说这接口背锅背得冤,他反手切出慢查日志,指着那行“482ms”的红色数字冷笑:“你管这叫冤?”我当场把杯子搁监控大屏边沿,屏保刚切到MySQL 5.7线程池曲线,那根标CPU的蓝线正抽风似地跳了一下,没两秒又平了——跟没发生过一样。 去年4月份,线上订单导出接口从三百七十二次调用里揪出十八毫秒那条。不是平均,是P99。不是压测,是凌晨三点灰度开关没推完,只开了七个节点,结果这十七个用户卡住,报警钉钉响了四十七下,我oncall手机震了一下,裤兜里手机压得我左腿发麻。我原以为又是索引失效,结果explain完发现主键走得好好的,连覆盖扫描都没问题。但count()和order by一起用的时候,MySQL愣是绕开联合索引,自己建临时表再filesort——就为省那二十毫秒的回表?我敢打包票,这个优化路径它根本没进成本模型,纯属直觉驱动。
文章配图,仅供参考 优胜劣汰不是选最快的,是淘汰最不肯改的。运维同事老周前天还拿旧版本配置来问:能不能把innodb_buffer_pool_instances调成16?我说调吧,反正你上线前也未必记得关掉slow_query_log_slow_admin_statements。他说测试环境报错了,我没问哪错的,就让他先去倒了杯水——水是茶水间新换的碧螺春,纸杯上印着去年Q3的OKR标语:“数据不落地,服务不降级”。他倒水回来时我正看那个慢查执行计划的trace,里面有一段cost评估写着“heuristic index condition pushdown rejected”,括号里备注是“index is too narrow for WHERE clause AND ORDER BY”,但WHERE其实只用了单字段。我点了三遍才确认没眼花:是优化器自己画蛇添足,把ORDER BY字段当WHERE条件塞进ICP预判逻辑里去了。后来怎么解的?加hint。FORCE INDEX (idx_user_status_created)。就这么一行,不是重写SQL,不是建冗余索引,就是硬按着脖子往坑里走——反而快了。上线那天测试跑回归用例跑了五遍,第三次失败是因为有个case里created_at字段传的是字符串“0000-00-00”,不是NULL也不是时间戳,导致索引失效,但那个case早该下线了。我们没人动它,就挂着,像公司楼下那台永远修不好的ATM机,贴着“暂停服务”纸条,底下被涂鸦成“请给我一个理由”。 KPI这事真别提。去年底评审,我交了二十三份优化报告,其中十一份结论是“无需优化”,因为业务方在迭代会上自己砍掉了那个功能。剩下十二份里,八份最后被前端加了loading骨架屏糊弄过去,两份靠加缓存扛住,一份我悄悄把查询拆成两次——第一次查ID列表,第二次IN查详情,接口耗时从四百多压到六十八,但DBA团队群聊里有人说“这种写法违反范式”,我说对,所以我也加了注释:“此处为性能妥协,下次重构请删此段,并附一张手绘ER图作为赎罪券”。没人回。群里头像全灰着。 说句难听的:现在谁还真盯execution time?盯着的是error rate、P95延迟告警频次、还有SLO仪表盘右下角那个不断跳动的“未处理SLA偏差”小红点。上周财务系统查账单,一个简单JOIN跑了两秒十六,DBA老大直接发话:“加列存”。我说列存解决不了笛卡尔积,他说“你加不加?”我说加,但我得先把中间表的PARTITION BY year_month干掉——它每季度自动建一次分区,但没人删过废弃分区,数据目录里躺着三十七个空子目录,最大的那个占着十五G磁盘空间,全是元数据碎片。他听完就走了,微信留了个句号。我也没追,反正他明天还得回来,因为备份策略脚本里有一行rm -rf写死路径,没做exists判断。 所以别信什么“毫秒级优化”,信灰度没推完时那七个节点的真实抖动。信oncall手机震了一下之后,你摸裤子口袋时指尖沾上的汗。信监控大屏上那根无关曲线抖完就停的节奏——有时候问题不是出在数据库,是出在你盯着它太久,眼睛开始自动补帧。这事儿我没法教新人,教了他们反而更怕。我现在让新人先读三个月error.log,不许碰任何配置,也不许建索引。就坐在那儿,数那些带“Got timeout reading communication packets”的日志条数。数到第十四万三千六百零二条,他们自然就懂什么叫“优胜劣汰”——不是机器淘汰人,是人在半夜三点放弃解释,转身去改hint的时候,淘汰了旧的自己。 下周一晨会我要提个事:能不能把慢查阈值从五百毫秒,调成二百五十?不为别的,就为了让某些SQL能早点进慢日志,别等到它自己学会装死。至于具体怎么调……算了,先看看研发那边能不能把那个传“0000-00-00”的bug排进下周迭代。如果排不进,我就把hint改成/+ USE_INDEX() /,再配个SQL comment写:“此处应有审计日志,但暂时欠费”。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


PHP实时交互卡顿?3步优化方案
创业合规与数据安全双轨协同优化路径
Windows多媒体站点权限配置优化方案
源码到执行全链路硬核优化,闭环打通
鸿蒙开发者必修:MySQL运维设计实战
数据驱动增长:客户端工程师的传媒网站响应式优化实践
系统优化与容器编排:高效服务器实践
