MySQL慢查询排查指南:EXPLAIN分析、索引优化与SQL改写思路

MySQL 慢查询是数据库优化中最常见的问题之一。页面打开慢、接口响应慢、后台列表卡顿,很多时候并不是程序语言本身慢,而是某条 SQL 扫描了太多数据、没有走索引,或者排序和关联方式不合理。

排查慢查询不能只凭感觉改 SQL,也不能看到慢就盲目加索引。更稳妥的流程是:先定位慢 SQL,再用 EXPLAIN 分析执行计划,确认扫描行数、索引使用情况和排序方式,最后再决定是加索引、改 SQL 还是调整业务查询方式。

先定位慢 SQL

排查慢查询的第一步,是找到真正慢的 SQL。可以从应用日志、接口耗时日志、数据库慢查询日志中定位。不要只根据用户说“页面慢”就直接猜是哪张表。

slow_query_log = 1
long_query_time = 1

慢查询日志可以记录超过指定时间的 SQL。线上环境开启前要评估日志量,并做好日志轮转,避免日志文件过大。

看执行计划

找到慢 SQL 后,使用 EXPLAIN 查看执行计划。

EXPLAIN SELECT * FROM orders WHERE user_id = 1001 ORDER BY created_at DESC;

EXPLAIN 能告诉你 MySQL 准备如何执行这条 SQL,包括使用了哪个索引、预计扫描多少行、是否需要额外排序等。

MySQL慢查询排查教程配图:EXPLAIN分析与索引优化
慢查询优化要先看执行计划,再决定是加索引、改 SQL 还是调整业务查询方式。

type 字段

type 表示访问类型,常见值包括 ALLindexrangerefeq_refconst 等。一般来说,ALL 表示全表扫描,需要重点关注。

但不是所有 ALL 都一定有问题。如果表很小,全表扫描可能比走索引更快。优化要结合数据量和业务场景判断。

key 和 possible_keys

possible_keys 表示可能使用的索引,key 表示实际使用的索引。如果 possible_keys 有值但 key 为空,说明 MySQL 最终没有使用这些索引。

这时要检查查询条件是否写法不合适,比如字段上用了函数、类型不一致、条件选择性太低,或者索引字段顺序不匹配。

rows 字段

rows 表示 MySQL 预计扫描的行数。这个数字越大,通常查询成本越高。慢查询里如果 rows 非常大,就要重点分析过滤条件和索引。

需要注意 rows 是估算值,不一定完全准确,但足以帮助判断优化方向。

Extra 字段

Extra 会显示额外执行信息。常见内容包括 Using whereUsing indexUsing filesortUsing temporary

Using filesort 表示需要额外排序,Using temporary 表示使用临时表。它们不一定绝对有问题,但在大数据量查询中要重点关注。

索引缺失

最常见的慢查询原因是缺少合适索引。比如经常按 user_id 查询订单,却没有给这个字段建索引。

CREATE INDEX idx_user_id ON orders(user_id);

如果查询还会按创建时间排序,可以考虑联合索引。

CREATE INDEX idx_user_created ON orders(user_id, created_at);

联合索引顺序

联合索引字段顺序要匹配真实查询。比如常见条件是按用户筛选,再按时间排序,那么 (user_id, created_at) 通常比 (created_at, user_id) 更合适。

设计联合索引前要看高频 SQL,不要凭字段名字随意组合。

函数导致索引失效

在索引字段上使用函数,可能导致索引无法有效使用。比如按日期查询时写:

WHERE DATE(created_at) = '2026-05-07'

更推荐改成范围查询:

WHERE created_at >= '2026-05-07 00:00:00'
  AND created_at < '2026-05-08 00:00:00'

避免 SELECT *

列表页和接口查询不要习惯性写 SELECT *。只查需要的字段,可以减少 IO、网络传输和回表成本。

SELECT id, title, created_at FROM articles WHERE status = 'published';

字段越少,越容易利用覆盖索引。尤其是表里有 TEXT、JSON、大字段时,列表查询更应该明确字段。

分页慢查询

大 offset 分页也常导致慢查询。

SELECT * FROM articles ORDER BY id DESC LIMIT 100000, 20;

可以考虑减少返回字段、延迟关联,或者改用游标分页。

SELECT id, title FROM articles WHERE id < :last_id ORDER BY id DESC LIMIT 20;

关联查询优化

JOIN 慢时,要检查关联字段是否有索引、关联顺序是否合理、过滤条件是否能提前缩小数据范围。

如果关联后数据量很大,可以先筛选出小结果集,再做关联。不要让数据库在大表之间无索引关联。

慢查询不只靠索引

有些慢查询不是简单加索引能解决的。比如一次查询返回几十万行、复杂报表实时计算、模糊搜索前后都有通配符,这些可能需要分页、缓存、异步统计、全文搜索或单独的数据模型。

优化要服务业务,不要让一个页面请求承担过多工作。

常见错误

第一种错误是不看 EXPLAIN,直接加索引。第二种错误是给每个字段都加索引。第三种错误是索引字段上使用函数。第四种错误是列表页 SELECT *。第五种错误是深分页不优化。第六种错误是只关注数据库,不看接口整体耗时。

实践建议

MySQL 慢查询排查可以按这个流程:定位慢 SQL,查看 EXPLAIN,关注 type、key、rows、Extra,确认是否缺索引或索引顺序不对,再考虑 SQL 改写、字段裁剪、分页优化和缓存策略。

慢查询优化不是一次性工作。随着数据量增长,原本很快的 SQL 也可能变慢。保留慢查询日志和定期 review,是数据库长期稳定的基础。

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容