MySQL 慢查询优化实战:从慢日志、EXPLAIN 到索引与深分页改写

举报
yd_229207802 发表于 2026/11/05 09:34:15 2026/11/05
【摘要】 业务反馈接口变慢,监控里 RDS for MySQL 的 CPU 一路走高,这是很常见的场景。大多数情况下,罪魁祸首是少数几条没有走到合适索引的 SQL。这篇文章整理了一套从发现慢 SQL、用 EXPLAIN 分析,到改写和验证的流程,命令都可以直接复用。一、先把慢 SQL 找出来在华为云 RDS 控制台的「慢日志」页面可以查看慢 SQL 的统计,包括执行次数、平均耗时和扫描行数。如果想在实...

业务反馈接口变慢,监控里 RDS for MySQL 的 CPU 一路走高,这是很常见的场景。大多数情况下,罪魁祸首是少数几条没有走到合适索引的 SQL。这篇文章整理了一套从发现慢 SQL、用 EXPLAIN 分析,到改写和验证的流程,命令都可以直接复用。

一、先把慢 SQL 找出来

在华为云 RDS 控制台的「慢日志」页面可以查看慢 SQL 的统计,包括执行次数、平均耗时和扫描行数。如果想在实例里确认阈值,可以执行:

SHOW VARIABLES LIKE 'long_query_time';
SHOW VARIABLES LIKE 'slow_query_log';

排查时不要只盯着单次最慢的 SQL,更要看「总耗时 = 次数 × 平均耗时」最高的那几条,它们才是拖垮 CPU 的主力。

二、用 EXPLAIN 看执行计划

拿到 SQL 后,在测试环境或只读节点上执行:

EXPLAIN SELECT * FROM orders WHERE user_id = 1001 AND status = 'PAID' ORDER BY created_at DESC LIMIT 20;

重点看这几列:

  • type:出现 ALL 表示全表扫描,index 表示全索引扫描,ref、range 才是比较健康的访问方式。
  • key:实际使用的索引,为 NULL 说明没有用上索引。
  • rows:预估扫描行数,与最终返回行数差距越大,浪费越多。
  • Extra:出现 Using filesort 或 Using temporary,说明排序或分组需要额外开销。

三、常见的索引失效原因

1. 对索引列使用函数或计算。例如 WHERE DATE(created_at) = '2026-11-01',会让索引失效,应改成范围条件:

WHERE created_at >= '2026-11-01' AND created_at < '2026-11-02'

2. 隐式类型转换。手机号字段是 varchar,却用数字去比较 WHERE phone = 13800000000,MySQL 会把每行转换成数字再比较,索引同样用不上,应写成字符串 '13800000000'。

3. 模糊查询以通配符开头。LIKE '%abc' 无法利用 B+ 树索引,业务允许时改成前缀匹配,或引入专门的搜索方案。

4. 联合索引不满足最左前缀。已有索引 (user_id, status, created_at),如果查询只带 status 条件,就用不上这个索引。

5. 字符集或排序规则不一致。多表关联时,关联字段的字符集不同会造成转换,导致被驱动表走全表扫描。

四、针对性建立联合索引

上面那条查询按 user_id 等值过滤、status 等值过滤、再按 created_at 排序,合适的索引是:

ALTER TABLE orders ADD INDEX idx_user_status_created (user_id, status, created_at);

等值条件放前面,排序字段放最后,这样既能过滤又能避免 filesort。建索引前请注意:大表加索引会占用 IO 和 CPU,应选择业务低峰期,并确认磁盘空间充足;索引也不是越多越好,每多一个索引都会增加写入成本。

五、深分页的改写

类似 LIMIT 1000000, 20 的深分页,MySQL 需要先扫描并丢弃前一百万行。常见的改法是记录上一页最后一条的主键,用条件代替偏移量:

SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 20;

如果必须支持跳页,可以先用覆盖索引查出主键,再回表取数据:

SELECT o.* FROM orders o
JOIN (SELECT id FROM orders WHERE status='PAID' ORDER BY id LIMIT 1000000, 20) t ON o.id = t.id;

六、验证效果

改完之后不要只看 EXPLAIN,还要用真实数据验证:

  • 对比改动前后同一条 SQL 的 rows 和实际耗时。
  • 观察 RDS 监控中的 CPU 使用率、慢查询数量是否下降。
  • 用 SHOW INDEX FROM orders 检查是否有重复或冗余的索引,必要时清理。

七、小结

慢 SQL 优化的思路并不复杂:先按总耗时排序找出重点,再用 EXPLAIN 判断是否走了索引,最后针对原因修改 SQL 或补充索引,并用监控验证。养成上线前对核心 SQL 做 EXPLAIN 的习惯,比出问题后再救火省事得多。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。