在 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

  • 索引范围扫描,比如使用 <BETWEENINSELECT * FROM users WHERE age BETWEEN 18 AND 30;

8. index

  • 扫描整个索引,但不扫表;常见于 ORDER BYGROUP BYSELECT age FROM users;

9. ALL

  • 全表扫描,没有使用索引,性能最差。SELECT * FROM users WHERE age + 1 = 20;

✅ 如何优化 type

  • 避免出现 ALLindex 类型。
  • 加索引:为 WHEREJOINORDER BY 中用到的字段建立合适的索引。
  • 使用覆盖索引:避免回表操作。
  • 避免在 WHERE 条件中对字段进行函数或表达式运算。
  • 使用合适的连接顺序(表小的、过滤多的放前面)。