EXPLAIN 命令是 MySQL 中用于分析查询执行计划的重要工具。通过 EXPLAIN,你可以了解 MySQL 是如何执行查询的,包括表的访问方式、使用的索引、连接顺序等。这有助于优化查询性能。以下是 EXPLAIN 命令的详细解释:
基本语法
EXPLAIN [EXTENDED] SELECT ...;
输出字段
EXPLAIN 的输出结果包含多个字段,每个字段都有特定的含义:
id: 查询的标识符。如果查询包含子查询或联合查询,每个子查询或联合部分会有不同的 id。
select_type: 查询的类型,常见的有:
- SIMPLE: 简单查询,不包含子查询或联合。
- PRIMARY: 最外层的查询。
- SUBQUERY: 子查询中的第一个 SELECT。
- DERIVED: 派生表(即在 FROM 子句中的子查询)。
- UNION: 联合查询中的第二个或后续的 SELECT。
- DEPENDENT UNION: 联合查询中的第二个或后续的 SELECT,依赖于外部查询。
- DEPENDENT SUBQUERY: 子查询,依赖于外部查询。
- MATERIALIZED: 物化子查询。
table: 当前处理的表。
partitions: 匹配的分区(如果使用了分区表)。
type: 访问类型,表示 MySQL 如何查找表中的行。常见的访问类型从最佳到最差依次为:
- system: 表中只有一行数据(系统表)。
- const: 表中最多只有一行匹配,常用于主键或唯一索引。
- eq_ref: 常见于主键或唯一索引的等值查询。
- ref: 非唯一索引的等值查询。
- range: 索引范围扫描。
- index: 全索引扫描。
- ALL: 全表扫描。
possible_keys: 可能使用的索引列表。
key: 实际使用的索引。
key_len: 使用的索引长度。
ref: 与索引比较的列或常量。
rows: 估计需要检查的行数。
filtered: 表示根据表条件过滤后剩余的行数百分比。
Extra: 包含额外的信息,如:
- Using where: 使用了 WHERE 子句进行过滤。
- Using index: 使用了覆盖索引,不需要回表查询。
- Using temporary: 需要创建临时表。
- Using filesort: 需要进行排序操作。
- Using join buffer (Block Nested Loop): 使用了块嵌套循环连接。
- Impossible WHERE: WHERE 条件总是不成立。
- No tables used: 查询没有使用表,如 SELECT 1。
示例
假设有一个表 employees,包含以下列:id, name, department_id, salary,并且在 id 和 department_id 上有索引。
EXPLAIN SELECT * FROM employees WHERE department_id = 10;
解读
- id: 1,表示这是最外层的查询。
- select_type: SIMPLE,表示这是一个简单的查询。
- table: employees,表示当前处理的表。
- partitions: NULL,表示没有使用分区。
- type: ref,表示使用了非唯一索引的等值查询。
- possible_keys: idx_department_id,表示可能使用的索引。
- key: idx_department_id,表示实际使用的索引。
- key_len: 4,表示使用的索引长度为4字节。
- ref: const,表示与索引比较的值是常量。
- rows: 100,表示估计需要检查的行数。
- filtered: 100.00,表示根据表条件过滤后剩余的行数百分比。
- Extra: Using where,表示使用了 WHERE 子句进行过滤。
通过 EXPLAIN 的输出,你可以了解查询的执行计划,并据此优化查询性能。例如,如果 type 为 ALL,表示进行了全表扫描,可能需要添加索引以提高查询效率。