在 MySQL 中,使用 EXPLAIN
(或 EXPLAIN SELECT ...
)可以查看 SQL 语句的执行计划,而其中最重要的字段之一就是 type
。它表示 MySQL 在执行查询时访问数据表的方式(即访问类型),也叫做 连接类型(Join Type)。
这个字段的值越靠近 ALL(全表扫描),表示性能越差;越靠近 const 或 system,表示性能越好。
🔍 type
的所有类型按性能从好到差排序如下:
级别 | 类型 | 说明 |
---|---|---|
🟢 非常优 | system | 表仅有一行(例如 system 表),非常快 |
🟢 非常优 | const | 表中最多只有一个匹配行,通常用于主键或唯一索引查询 |
🟢 非常优 | eq_ref | 唯一索引扫描,针对每个来自前表的记录,精确匹配一条记录 |
🟡 较优 | ref | 非唯一索引扫描,返回匹配某个索引列值的所有行 |
🟡 中等 | fulltext | 使用全文索引进行全文搜索 |
🟠 一般 | ref_or_null | 类似 ref,但还包含对 NULL 值的额外查找 |
🟠 一般 | index_merge | 多个索引合并使用,MySQL 取并集/交集 |
🟠 一般 | unique_subquery | 对于某些 IN 子查询优化为唯一索引查找 |
🟠 一般 | index_subquery | 类似于上一个,但返回多值 |
🔴 较差 | range | 索引范围扫描,查找某个范围内的记录,如 BETWEEN 、< 、> |
🔴 较差 | index | 全索引扫描,遍历整个索引,避免回表但数据多时性能低 |
🔴 最差 | ALL | 全表扫描,没有用到索引,性能最差 |
📘 类型详解
1. system
- 表只有一行,系统表。
- 非常快的情况,极少见。
2. const
- 主键或唯一索引 + 常量查询,例如:
SELECT * FROM users WHERE id = 1;
- 最多匹配一行,MySQL 在优化阶段即确定结果。
3. eq_ref
- 针对连接操作中的子表,使用主键/唯一索引与外部表一对一匹配。
SELECT * FROM orders o JOIN users u ON o.user_id = u.id;
4. ref
- 使用非唯一索引查找,如普通索引字段的等值查询。
SELECT * FROM users WHERE name = 'Alice';
5. ref_or_null
- 查找索引匹配某值 或 NULL 的情况。
SELECT * FROM users WHERE referrer_id = 10 OR referrer_id IS NULL;
6. index_merge
- 多个索引联合使用(并集或交集)。
SELECT * FROM users WHERE age = 20 OR city = 'Beijing';
7. range
- 索引范围扫描,比如使用
<
、BETWEEN
、IN
。SELECT * FROM users WHERE age BETWEEN 18 AND 30;
8. index
- 扫描整个索引,但不扫表;常见于
ORDER BY
、GROUP BY
。SELECT age FROM users;
9. ALL
- 全表扫描,没有使用索引,性能最差。
SELECT * FROM users WHERE age + 1 = 20;
✅ 如何优化 type
?
- 避免出现
ALL
、index
类型。 - 加索引:为
WHERE
、JOIN
、ORDER BY
中用到的字段建立合适的索引。 - 使用覆盖索引:避免回表操作。
- 避免在
WHERE
条件中对字段进行函数或表达式运算。 - 使用合适的连接顺序(表小的、过滤多的放前面)。
发表回复