MySQL 的EXPLAIN 计划 type 字段详细说明

在 MySQL 的 EXPLAIN 执行计划中,type 字段表示查询的访问类型,即 MySQL 在查询时使用的数据检索方法。不同的 type 值表示不同的查询效率,通常 system 是最优的,而 ALL 是最差的。以下是这些 type 值的详细说明及其排序:

复制代码
system > const > eq_ref > ref > range > index > ALL

1. system(性能最优)

  • 说明

    • 该表只有一行记录(如 system 表,或者只有一条记录的 MyISAM 表)。
    • 相当于 const,但只适用于单行数据的情况。
  • 示例

    sql 复制代码
    EXPLAIN SELECT * FROM singleton_table;
  • 特点

    • 由于表只有一行,直接读取该行即可,不涉及索引扫描或全表扫描。
    • 访问代价极低。

2. const(常量查询)

  • 说明

    • 适用于 唯一索引(PRIMARY KEY 或 UNIQUE) 查询,并且查询条件是常量。
    • MySQL 仅需查询一次,就能获取数据。
    • 适用于 WHERE 子句中的主键或唯一索引等查询。
  • 示例

    sql 复制代码
    EXPLAIN SELECT * FROM employees WHERE emp_id = 100;
  • 特点

    • 查询结果最多返回一行。
    • 查询优化器会在编译阶段就确定查询结果,速度极快。
    • 适用于主键或唯一索引的等值查询。

3. eq_ref(唯一索引等值匹配)

  • 说明

    • eq_ref 用于 主键(PRIMARY KEY)或唯一索引(UNIQUE KEY) 的等值查询,通常出现在多表 JOIN 操作中。
    • 对于每一行来自主表的数据,子表最多只会返回一条匹配记录。
  • 示例

    sql 复制代码
    EXPLAIN 
    SELECT e.emp_id, d.dept_name 
    FROM employees e 
    JOIN departments d ON e.dept_id = d.dept_id;
  • 特点

    • 每次查询只返回一行数据 (因为 eq_ref 必须基于 PRIMARY KEYUNIQUE 索引)。
    • 查询优化效果非常好。
    • 常见于 JOIN 语句中,被连接表的主键或唯一索引用于匹配主表的字段。

4. ref(普通索引等值匹配)

  • 说明

    • ref 表示查询使用了非唯一索引(普通索引、非唯一的外键索引)。
    • 适用于非唯一索引或 JOIN 操作中的索引匹配,可能会返回 多行 数据。
  • 示例

    sql 复制代码
    EXPLAIN SELECT * FROM employees WHERE department_id = 5;
  • 特点

    • 使用索引查找,但不是唯一匹配(可能匹配多行)。
    • 常用于 JOIN 操作,或者在 WHERE 子句中使用非唯一索引的查询。

5. range(范围查询)

  • 说明

    • range 表示基于索引范围扫描,可以使用索引高效查找数据。
    • 常见的范围查询有 BETWEEN><IN 等。
  • 示例

    sql 复制代码
    EXPLAIN SELECT * FROM employees WHERE salary BETWEEN 5000 AND 10000;
  • 特点

    • 适用于索引列上的范围查询。
    • 扫描索引的部分数据,比全表扫描(ALL)高效。
    • 适用于 >, <, BETWEEN, IN() 等操作符。

6. index(全索引扫描)

  • 说明

    • index 表示 全索引扫描 ,相当于 ALL(全表扫描),但扫描的是索引而非数据行。
    • 适用于索引覆盖查询(即不需要回表查询)。
  • 示例

    sql 复制代码
    EXPLAIN SELECT idx_column FROM large_table;
  • 特点

    • 比全表扫描(ALL)稍快,因为索引通常比整个表小。
    • 不会使用 WHERE 过滤条件,会遍历整个索引。

7. ALL(全表扫描,性能最差)

  • 说明

    • ALL 表示 全表扫描,意味着 MySQL 需要遍历整个表的所有数据行。
    • 适用于无索引的查询,或者查询无法利用索引。
  • 示例

    sql 复制代码
    EXPLAIN SELECT * FROM employees WHERE name = 'John Doe';
  • 特点

    • 性能最差,因为需要扫描整张表。
    • MySQL 可能会自动使用 Using filesortUsing temporary 进行排序。
    • 如果 ALL 出现在大表查询中,通常需要优化索引

总结与排序

访问类型 适用情况 典型场景 速度
system 只有一行数据的表 读取单行数据 最快
const 主键或唯一索引等值查询 WHERE id = 1 极快
eq_ref 主键或唯一索引 JOIN 查询 JOIN ON primary_key 非常快
ref 非唯一索引等值查询 WHERE department_id = 5
range 范围查询 WHERE age BETWEEN 18 AND 30 中等
index 全索引扫描 SELECT idx_column FROM table 较慢
ALL 无索引查询或全表扫描 SELECT * FROM large_table 最慢

优化建议

  1. 避免 ALL(全表扫描)

    • 创建索引,提高查询效率。
    • 使用 EXPLAIN 分析执行计划,确认索引是否被使用。
  2. 优化 range(范围扫描)

    • 适当调整索引,避免 MySQL 过度扫描数据范围。
    • 使用 BETWEENIN() 查询时,确保索引列的数据分布合理。
  3. 提升 refeq_ref 查询

    • 使用外键关系,并确保 JOIN 语句涉及索引列。
    • 采用 覆盖索引,减少回表查询的次数。
  4. 优化 index(全索引扫描)

    • 避免 SELECT *,只查询必要字段,减少数据量。
    • 确保查询能利用索引,避免额外的 Using filesortUsing temporary

通过这些优化方法,可以减少数据库的负载,提高查询速度。

相关推荐
maki0775 分钟前
VR大空间资料 04 —— VRAF使用体验和源码分析
android·vr·虚幻·源码分析
养生技术人36 分钟前
Oracle OCP认证考试题目详解082系列第48题
运维·数据库·sql·oracle·database·开闭原则·ocp
海阳宜家电脑1 小时前
Lazarus使用TSQLQuery更新的一点技巧
数据库·lazarus·tsqlquery
丨我是张先生丨2 小时前
SQLSERVER 查找存储过程中某个变量
数据库
感谢地心引力2 小时前
【Python】基于 PyQt6 和 Conda 的 PyInstaller 打包工具
数据库·python·conda·pyqt·pyinstaller
消失的旧时光-19432 小时前
Kotlin 判空写法对比与最佳实践
android·java·kotlin
锅拌饭3 小时前
Android Handler(一) 同步屏障泄露导致页面假死
android
锅拌饭3 小时前
Android Handler(二) 同步屏障泄露检测
android
韩立学长3 小时前
【开题答辩实录分享】以《走失人口系统档案的设计与实现》为例进行答辩实录分享
mysql·mybatis·springboot