上一节我们学习了:
索引是什么,以及索引为什么能提高查询速度。
但是实际开发中会遇到一个问题:
CREATE INDEX idx_name ON user(name);创建了索引以后:
SELECT * FROM user WHERE name='Tom';真的使用索引了吗?
为什么有时候:
明明有索引,SQL 还是很慢?
这就需要学习:
EXPLAIN
一、什么是 EXPLAIN?
定义:
EXPLAIN 是 MySQL 提供的 SQL 执行计划分析工具,用来查看 MySQL 如何执行一条 SQL。
简单理解:
你写 SQL:
SELECT * FROM user WHERE name='Tom';MySQL 内部会决定:
方案A: 扫描整张表 方案B: 使用索引查询EXPLAIN 可以告诉我们:
MySQL 最终选择了哪个方案。
二、基本使用
语法:
EXPLAIN SQL语句;例如:
EXPLAIN SELECT * FROM user WHERE name='Tom';返回:
| 字段 | 含义 |
|---|---|
| id | 查询编号 |
| select_type | 查询类型 |
| table | 查询表 |
| type | 访问类型 |
| possible_keys | 可能使用的索引 |
| key | 实际使用的索引 |
| rows | 预计扫描行数 |
| Extra | 额外信息 |
三、EXPLAIN 输出示例
假设:
user 表:
100万数据有索引:
CREATE INDEX idx_name ON user(name);执行:
EXPLAIN SELECT * FROM user WHERE name='Tom';结果:
| 字段 | 值 |
|---|---|
| table | user |
| type | ref |
| possible_keys | idx_name |
| key | idx_name |
| rows | 10 |
说明:
MySQL:
✅ 找到了索引
✅ 使用了索引
✅ 只需要扫描10行
四、重点字段解析
1. type(最重要)⭐⭐⭐⭐⭐
type 表示:
MySQL 访问数据的方式。
性能从好到差:
system ↓ const ↓ eq_ref ↓ ref ↓ range ↓ index ↓ ALL① system
最快。
只有一条数据。
例如:
系统表。
② const
主键查询。
例如:
SELECT * FROM user WHERE id=1;因为:
id 是主键。
MySQL:
直接定位。
③ eq_ref
多表 JOIN 中常见。
例如:
SELECT * FROM orders o JOIN user u ON o.user_id=u.id;④ ref
普通索引查询。
例如:
WHERE username='Tom'⑤ range
范围查询。
例如:
WHERE age BETWEEN 18 AND 30;使用索引范围扫描。
⑥ ALL(危险)⭐⭐⭐⭐⭐
表示:
全表扫描。
例如:
SELECT * FROM user;或者:
索引失效。
五、重点字段 key ⭐⭐⭐⭐⭐
key:
表示:
实际使用的索引。
例如:
结果:
key = idx_name说明:
使用:
idx_name如果:
key = NULL表示:
没有使用索引。
六、possible_keys
表示:
可能使用的索引。
例如:
possible_keys: idx_name说明:
MySQL 认为:
这个索引可能有帮助。
但是:
最终是否使用:
看 key。
区别:
| 字段 | 含义 |
|---|---|
| possible_keys | 可能使用 |
| key | 实际使用 |
七、rows(非常重要)
rows:
表示:
MySQL 预计需要扫描多少行。
例如:
情况1:
rows = 10很好。
情况2:
rows = 1000000说明:
扫描大量数据。
SQL 可能需要优化。
八、Extra 字段
Extra 是非常重要的信息。
1. Using index
表示:
覆盖索引。
例如:
索引:
(name, age)查询:
SELECT name,age FROM user;不用回表。
很好。
2. Using where
表示:
使用 WHERE 过滤。
正常。
3. Using filesort ⭐⭐⭐⭐⭐
危险。
表示:
额外排序。
例如:
ORDER BY create_time;但是:
没有索引。
MySQL:
查询完数据后再排序。
优化:
增加索引:
CREATE INDEX idx_time ON user(create_time);4. Using temporary ⭐⭐⭐⭐⭐
危险。
表示:
使用临时表。
常见:
GROUP BY ORDER BY优化空间较大。
九、判断 SQL 是否优秀
一个好的 SQL:
通常:
type: const/ref/range key: 有值 rows: 较少 Extra: 没有 filesort 没有 temporary十、索引为什么存在但没有使用?
这是企业开发高频问题。
① 使用函数
索引:
name查询:
WHERE LOWER(name)='tom'索引失效。
原因:
MySQL 需要计算后比较。
② LIKE 前面使用 %
例如:
WHERE name LIKE '%Tom'无法定位开头。
索引失效。
但是:
WHERE name LIKE 'Tom%'可以使用索引。
③ 类型转换
字段:
phone VARCHAR(20)查询:
WHERE phone=13800000000可能导致转换。
④ 使用 OR
例如:
WHERE name='Tom' OR age=20;可能导致索引失效。
十一、EXPLAIN 实际开发流程
开发中:
发现 SQL 慢:
↓
第一步:
EXPLAIN SQL;↓
看:
type key rows Extra↓
发现:
type=ALL↓
分析:
为什么没有索引?
↓
优化:
增加索引 / 修改 SQL
十二、本节总结
| 字段 | 作用 |
|---|---|
| type | 访问方式,判断性能 |
| possible_keys | 可能使用索引 |
| key | 实际使用索引 |
| rows | 扫描数量 |
| Extra | 额外执行信息 |
🎯 本节核心一句话:
EXPLAIN 是 MySQL 性能分析的“诊断工具”,它告诉我们 SQL 有没有走索引、扫描多少数据,以及为什么慢。