一、EXPLAIN 的作用

        EXPLAIN 用于分析 SQL 执行计划,帮助我们了解 MySQL 在执行查询时的策略,从而判断性能瓶颈。

        explain 是查看 sql 的执行计划,主要用来分析 sql 语句的执行过程,比如有没有走索引,有没有外部排序,有没有索引覆盖等等。


使用方式:

EXPLAIN SELECT * FROM user WHERE age > 18;

EXPLAIN 输出的关键字段说明

  1. id

    • 查询中每个 SELECT 的标识号,值越大优先级越高。

    • 复杂 SQL(子查询/联合查询)时用于区分执行顺序。

  2. select_type

    • 查询类型:

      • SIMPLE:简单查询(无子查询、UNION)。

      • PRIMARY:最外层查询。

      • SUBQUERY:子查询。

      • DERIVED:派生表(FROM 子句中的子查询)。

      • UNION:UNION 中第二个及以后的查询。

  3. table

    • 当前行对应的表。

  4. type(最重要,表示连接方式,性能从好到坏依次是):

    • system > const > eq_ref > ref > range > index > ALL

    • ALL 表示全表扫描,是最差的,需要重点优化。

  5. possible_keys

    • 可能用到的索引。

  6. key

    • 实际使用的索引。

  7. key_len

    • 索引使用的字节数,越小越精确。

  8. ref

    • 哪些列或常量与索引进行比较。

  9. rows

    • 预计扫描的行数(值越小越好)。

  10. Extra

  • 补充信息:

    • Using index:索引覆盖。

    • Using where:需要回表。

    • Using filesort:排序时没用索引,需要额外排序。

    • Using temporary:使用了临时表(常见于 GROUP BY)。

补充:


二、慢 SQL 排查思路

1. 开启慢查询日志

 (1)👉 我们可以通过设置 long_query_time 参数来定义 SQL 执行时间超过多少秒就被认为是“慢查询”。
# my.cnf 配置文件
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/slow.log
long_query_time = 1   # 超过1秒的SQL记录为慢查询

        这样配置后,MySQL 会把执行时间超过 1 秒 的 SQL 记录到 slow.log 文件里。

查看慢 SQL:

   (2)👉 这个命令的作用是 查看当前 MySQL 慢查询日志功能是否开启。 

SHOW VARIABLES LIKE 'slow_query_log';

返回结果会是:

Variable_name Value
slow_query_log ON
  • 如果是 ON,说明已启用慢查询日志。

  • 如果是 OFF,说明没启用。

2. 分析慢 SQL 的工具

  • EXPLAIN:查看执行计划。

  • SHOW PROFILE:分析 SQL 在各个阶段的耗时。

  • pt-query-digest:Percona 提供的日志分析工具。


三、常见慢 SQL 场景与优化方法

1. 全表扫描

SELECT * FROM user WHERE age = 20;
  • 原因:没有索引,或索引失效。

  • 解决:给 age 加索引。


2. 索引未命中

SELECT * FROM user WHERE age = 20;
  • 原因:对索引字段做了函数运算。

  • 解决:不要对索引列做函数操作,可新增前缀索引 INDEX(name(3))


3. 覆盖索引未使用

SELECT id, name FROM user WHERE age = 18;
  • 优化:建联合索引 (age, id, name),避免回表,减少 IO。


4. Using filesort

SELECT * FROM user ORDER BY age;
  • 原因:排序字段未使用索引。

  • 解决:为 age 建索引,或使用联合索引覆盖 ORDER BY。


5. Using temporary

SELECT age, COUNT(*) FROM user GROUP BY age;
  • 原因:没有合适的索引。

  • 解决:建立索引 (age)


6. IN 过大

SELECT * FROM user WHERE id IN (1,2,3,...,10000);
  • 原因:IN 列表过大,效率低。

  • 优化

    • 改用 JOIN

    • 或用临时表存储 ID 再查询。


7. OR 查询

SELECT * FROM user WHERE age = 20 OR name = 'Tom';
  • 原因:OR 会导致索引失效。

  • 优化:使用 UNION ALL 拆分。

    • UNION ALLSQL 中的集合操作符,它的作用是把两个或多个查询结果合并在一起,并且 不去重

SELECT * FROM user WHERE age = 20
UNION ALL
SELECT * FROM user WHERE name = 'Tom';

四、慢 SQL 优化总结

  1. 索引优化

    • 索引要覆盖常用查询条件、排序和分组字段。

    • 联合索引遵循 最左前缀原则

    • 避免函数、隐式转换导致索引失效。

  2. SQL 优化

    • 少用 SELECT *,只查必要字段。

    • 拆分复杂 SQL,减少子查询,改用 JOIN。

    • 大数据分页优化:LIMIT offset, size → 改成 LIMIT size + 记住上次 ID。

  3. 架构优化

    • 分库分表。

    • 读写分离。

    • 使用缓存(Redis)。


一句话总结

  • EXPLAIN 用来分析 SQL 执行计划,重点关注 type、rows、Extra

  • 慢 SQL 排查从 索引、SQL 写法、架构 三个层面优化。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐