MySQL的explain
时间: 2025-05-25 13:08:52 浏览: 18
### MySQL 中 EXPLAIN 的用法及结果解读
#### 什么是 EXPLAIN?
`EXPLAIN` 是 MySQL 提供的一种工具,用于分析 SQL 查询的执行计划。通过 `EXPLAIN` 关键字,可以查看优化器如何处理查询语句,包括表的读取顺序、数据读取操作类型、使用的索引等信息[^1]。
---
#### 基本语法
```sql
EXPLAIN SELECT ...;
```
将任意一条 `SELECT` 查询语句附加到 `EXPLAIN` 后面即可获取该查询的执行计划。
---
#### 结果列解析
| 字段名 | 描述 |
|--------------|----------------------------------------------------------------------------------------|
| `id` | 查询中每个 SELECT 子句的序列号。值越小优先级越高。 |
| `select_type`| 显示查询的类型,例如 SIMPLE(简单查询)、PRIMARY(主查询)、SUBQUERY(子查询)等[^3]。 |
| `table` | 输出结果集中的表名称或派生表(Derived Table)。 |
| `partitions` | 如果启用了分区,则显示匹配的分区列表。 |
| `type` | 访问类型,表示 MySQL 如何查找表中的行。常见值有 ALL、INDEX、RANGE、REF 等[^4]。 |
| `possible_keys`| 可能使用的索引列表。 |
| `key` | 实际使用的索引名称。 |
| `key_len` | 使用的索引长度,单位为字节。 |
| `ref` | 列出与索引比较的内容,可能是常量或其他表的列。 |
| `rows` | 估计需要扫描的行数。 |
| `filtered` | 表示在存储引擎检索后,服务器端过滤掉的比例(百分比)。 |
| `Extra` | 包含额外的信息,如 Using where、Using index、Using temporary 等[^2]。 |
---
#### 解析关键字段
##### 1. `type` 字段
`type` 字段反映了访问类型的质量,按性能从高到低排列如下:
- **system**:表只有一行记录。
- **const**:通过唯一索引直接定位单行数据。
- **eq_ref**:对于每个来自前面表的行组合,最多只有一个匹配行。
- **ref**:非唯一索引扫描,返回所有匹配某个值的行。
- **range**:仅检索给定范围内的行,使用索引来选择行。
- **index**:全索引扫描,遍历整个索引树。
- **ALL**:全表扫描,性能最低。
推荐目标是让大部分查询达到 `range` 或更高级别[^4]。
##### 2. `rows` 字段
`rows` 表示 MySQL 估算的需要扫描的行数。理想情况下,应尽量减少此数值。可以通过观察各表间 `rows` 的乘积来判断整体查询效率[^2]。
##### 3. `Extra` 字段
`Extra` 提供了更多关于查询执行的补充信息。常见的值及其含义包括:
- **Using Where**:MySQL 正在使用 WHERE 子句筛选行。
- **Using Index**:覆盖索引,无需回表查询。
- **Using Temporary**:需要创建临时表来处理查询。
- **Using Filesort**:需要进行排序操作,可能导致性能下降。
---
#### 示例分析
假设有一个查询如下:
```sql
EXPLAIN SELECT * FROM goods_spec WHERE id IN (
SELECT id FROM goods WHERE id < 2
UNION
SELECT goods_id FROM goods_spec_price WHERE goods_id < 2
);
```
执行结果可能类似于以下表格:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
|-----|----------------------|-----------------|--------|---------------|---------|---------|------|------|-----------------------|
| 1 | PRIMARY | goods_spec | ALL | NULL | NULL | NULL | NULL | 100 | Using where |
| 2 | DEPENDENT SUBQUERY | goods | RANGE | PRIMARY | PRIMARY | 8 | NULL | 1 | Using where |
| 3 | DEPENDENT SUBQUERY | goods_spec_price| RANGE | idx_goods_id | idx_goods_id | 8 | NULL | 1 | Using where |
**解读**:
- 主查询 (`goods_spec`) 进行了全表扫描 (`ALL`),这通常是不理想的。
- 子查询分别对 `goods` 和 `goods_spec_price` 使用了索引 (`RANGE`),表明它们的条件得到了良好支持。
- 整体查询涉及依赖子查询 (`DEPENDENT SUBQUERY`),可能会降低性能。
---
#### 性能优化建议
1. 尽量避免全表扫描 (`ALL`),改用合适的索引。
2. 减少 `rows` 数值,特别是大表上的扫描次数。
3. 避免不必要的临时表 (`Using Temporary`) 和文件排序 (`Using Filesort`)。
4. 对于复杂查询,考虑拆分为主查询和派生表 (Derived Table),并合理利用索引[^3]。
---
阅读全文
相关推荐









