SQL 运行较慢的按照这个来排查一下就差不多了

“一条SQL卡了3秒,老板在群里@你,客户在微信里骂娘,你怎么回?

SQL 运行较慢的按照这个来排查一下就差不多了

SQL 运行较慢的按照这个来排查一下就差不多了

别急着甩锅,先摸一把冷汗,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把一整天的心情都拖成慢查询。

SQL 运行较慢的按照这个来排查一下就差不多了

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...