Bohr-L Bohr-L
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

刘博

I'm a slow walker, But I never walk backwards.
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 数据处理与存储类

  • Spring 生态类

  • 缓存问题类

  • 多线程类

  • JVM 类

  • MySQL 类

    • MySQL 为什么一定要有一个主键
    • MySQL 中的 RR 隔离级别,到底有没有解决幻读问题
    • MySQL 的行级锁到底锁的是什么东西?
    • 存储 MD5 值应该用 VARCHAR 还是用 CHAR?
    • 数据库的三范式是什么?
    • 说说 InnoDB 与 MyISAM 的区别
    • drop、truncate、delete 的区别
    • 聊一聊数据库事务机制
    • 聊一聊 MySQL 中的关联查询
    • 事务隔离级别有哪些?MySQL 的默认隔离级别是什么
    • 分库分表之后,id 主键如何处理?
    • 说说在 MySQL 中一条查询 SQL 是如何执行的?
    • 讲解下 DDL、DML、DCL
    • 存储过程和触发器的作用
    • MySQL 如何行转列和列转行
    • 如何查看 SQL 的执行计划
      • union 和 unionAll 的区别
      • having 和 where 的区别
      • 常见的索引原则
      • MySQL 中的 IN 和 EXISTS 子句有什么区别?
      • MySQL 如何处理 NULL 值,对性能有什么影响?
      • 如何在 MySQL 中处理和避免全表扫描?
      • MySQL 中的表空间是什么,它的作用是什么?
      • 在 MySQL 中,如何优化 ORDER BY 查询?
    • Java 8 + 特性类

    • 其他技术类

    • 常见面试题
    • MySQL 类
    刘博
    2025-12-29
    目录

    如何查看 SQL 的执行计划

    查看 SQL 执行计划是 “优化 SQL 性能” 的核心步骤,通过EXPLAIN命令可获取 MySQL 优化器生成的执行计划,了解 SQL 的执行方式(如是否使用索引、扫描行数、关联顺序等),从而定位性能瓶颈。

    # 1. 基本用法

    在查询 SQL 前添加EXPLAIN关键字,即可查看执行计划:

    -- 查看单表查询执行计划
    EXPLAIN SELECT * FROM user WHERE age > 20;
    
    -- 查看多表关联查询执行计划
    EXPLAIN SELECT u.name, o.order_id FROM user u JOIN `order` o ON u.id = o.user_id WHERE u.age > 20;
    
    1
    2
    3
    4
    5

    # 2. 执行计划核心字段解析

    执行计划返回的字段中,关键字段如下(重点关注带★的字段):

    字段名 核心含义
    ★ id 执行顺序标识:id 相同,按从上到下顺序执行;id 不同,id 越大优先级越高(子查询先执行)
    ★ select_type 查询类型:SIMPLE(简单查询,无子查询)、SUBQUERY(子查询)、DERIVED(派生表)、JOIN(关联查询)
    ★ table 执行查询的表(或派生表别名、子查询别名)
    ★ type 访问类型(索引使用效率):从优到差为 system > const > eq_ref > ref > range > index > ALL
    ★ possible_keys 可能使用的索引(MySQL 认为适合的索引)
    ★ key 实际使用的索引(若为 NULL,说明未使用索引,可能全表扫描)
    key_len 实际使用的索引长度(越长,索引过滤性越好)
    ★ rows MySQL 预估的扫描行数(越少,性能越好)
    ★ Extra 额外信息(如 Using index:覆盖索引、Using where:使用 WHERE 过滤、Using filesort:文件排序、Using temporary:临时表)

    # 3. 关键字段详解

    # (1)type 字段(访问类型,核心关注)
    • system:表中只有一行数据(如系统表),性能最优;
    • const:通过主键或唯一索引查询,只返回一行数据(如WHERE id=1);
    • eq_ref:多表关联时,被驱动表通过主键或唯一索引匹配(如user.id = order.user_id,order 表的 user_id 是主键);
    • ref:通过非唯一索引匹配(如WHERE name='张三',name 是普通索引);
    • range:索引范围查询(如WHERE age BETWEEN 20 AND 30、WHERE id IN (1,2,3));
    • index:扫描整个索引(如SELECT id FROM user,id 是索引,无需访问数据文件);
    • ALL:全表扫描(性能最差,需优化,如添加索引)。
    # (2)Extra 字段(额外信息,核心关注)
    • Using index:覆盖索引(查询字段均在索引中,无需回表),性能好;
    • Using where:使用 WHERE 子句过滤数据(索引未过滤全部数据,需在内存中过滤);
    • Using filesort:文件排序(未使用索引排序,需在磁盘或内存中排序,性能差,需优化索引,如ORDER BY字段添加索引);
    • Using temporary:创建临时表(如GROUP BY未使用索引,需创建临时表存储分组结果,性能差);
    • Using join buffer:关联查询时使用连接缓冲区(被驱动表未使用索引,需缓存驱动表数据匹配,性能差);
    • Impossible WHERE:WHERE 条件恒假(如WHERE 1=2),无数据返回。

    # 4. 执行计划分析示例

    示例 SQL:EXPLAIN SELECT * FROM user WHERE age > 20 AND name LIKE '张%'

    执行计划结果(关键字段):

    id select_type table type possible_keys key rows Extra
    1 SIMPLE user range idx_age_name idx_age_name 100 Using where

    分析:

    • type=range:使用索引范围查询(age>20+name LIKE ' 张 %',匹配索引idx_age_name);
    • key=idx_age_name:实际使用了联合索引idx_age_name(age 在前,name 在后,符合最左前缀原则);
    • rows=100:预估扫描 100 行,性能较好;
    • Extra=Using where:索引过滤后,需进一步过滤数据(无问题)。

    若执行计划中 key=NULL、type=ALL,说明未使用索引,需添加索引(如CREATE INDEX idx_age_name ON user(age, name))。

    # 5. 扩展:EXPLAIN EXTENDED(查看优化后的 SQL)

    EXPLAIN EXTENDED可查看 MySQL 优化器改写后的 SQL(如简化条件、改写关联顺序),帮助理解优化逻辑:

    EXPLAIN EXTENDED SELECT * FROM user WHERE age > 20 AND age < 30;
    -- 执行后,通过SHOW WARNINGS查看改写后的SQL
    SHOW WARNINGS;
    
    1
    2
    3

    #


    上次更新: 12/30/2025
    MySQL 如何行转列和列转行
    union 和 unionAll 的区别

    ← MySQL 如何行转列和列转行 union 和 unionAll 的区别→

    最近更新
    01
    CPU 使用率较高排查和解决
    12-29
    02
    JVM OOM 问题如何排查和解决
    12-29
    03
    接口防刷怎么实现?
    12-29
    更多文章>
    Theme by Vdoing | Copyright © 2025-2026 Bohr-L's note
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式