SQL 运行较慢的按照这个来排查一下就差不多了
“一条SQL卡了3秒,老板在群里@你,客户在微信里骂娘,你怎么回?

”

别急着甩锅,先摸一把冷汗,90%的“慢查询”实则五分钟就能摁死,只是多数人还在用五年前的老办法。
——打开慢日志,拉到最上面那条,rows_examined 七位数,基本宣判死刑。
——复制SQL,EXPLAIN一贴,type=ALL,key=NULL,得,全表扫描。
——再瞄一眼Extra,Using filesort+Using temporary,双杀,内存和磁盘一起爆炸。
这三步做完,病根已经写在脸上:没索引,或索引用不上。
老套路是“加索引、改SQL、再跑一遍”,目前云厂商把饭喂到嘴边:
阿里云的DBMind直接弹窗“提议建联合索引(col1,col2)”,一键生效,灰度都省了;
AWS的Query Advisor更狠,把OR条件拆成UNION ALL,重写后的SQL执行时间从2.8秒掉到0.07秒,连回滚键都不用按。
别嫌贵,RDS自带这些功能,不开白不开。
MySQL 8.0.34还有个隐藏彩蛋:倒序索引免费提速。
订单表按create_time DESC查最新50条,以前只能走filesort,目前一条
CREATE INDEX idx_time_desc ON orders(create_time DESC);
执行计划里Extra瞬间干净,晚上12点批处理不再把CPU打到100%,监控曲线从心电图变成直线,运维小哥终于能睡觉。
有人吐槽:“索引加了十几条,查询还是慢。
”
八成是踩了“函数索引”的坑。
DATE_FORMAT(create_time,'%Y-%m') = '2024-05' 这种写法,8.0之前只能全表扫;
8.0.28后来支持函数索引,
CREATE INDEX idx_month ON orders((DATE_FORMAT(create_time,'%Y-%m')));
同一句话,成本从百万行降到百行,效果肉眼可见。
记得把表达式用括号包起来,不然优化器当没看见,别问我是怎么知道的。
复杂查询别硬刚,Performance Schema里现成有“Top 10 最慢指纹”:
SELECT schema_name, digest_text, avg_timer_wait/1e12 AS avg_sec
FROM events_statements_summary_by_digest
ORDER BY avg_timer_wait DESC LIMIT 10G
复制digest_text,丢进SQL窗口,前面加EXPLAIN FORMAT=TREE,
执行树一层层展开,哪个地方扇出爆炸一眼锁定。
比扒slow log省掉grep+awk+sed三连,头发都少掉两根。
分区表也别再按时间RANGE死磕,LIST COLUMNS新玩法更丝滑。
订单状态只有几种:待支付、已支付、已发货、已完成,
用状态做LIST分区,查询带上WHERE status='已支付',直接裁剪掉四分之三的分区,
再配上线性HASH,运维半夜再也不用爬起来手工ADD PARTITION。
最后一步验证,别只会“再跑一遍看时间”。
MySQL Shell里敲:
util.checkForServerUpgrade()
能把隐藏配置坑全翻出来:
innodb_buffer_pool_instances太小、tmp_table_size撞到内存上限、甚至主从半同步延迟,报告一条不落。
顺手开optimizer_trace,优化器为什么放弃索引选全表,写在JSON里,比DBA拍脑袋靠谱。
总结一句话:
慢SQL像厨房蟑螂,看见一条,背后已经藏了一百条。
把云厂商的新玩具、8.0的小彩蛋、Performance Schema的现成报表全部用上,
五分钟定位,五分钟修复,剩下的时间用来泡咖啡,别让一条SQL把一整天的心情都拖成慢查询。



