针对上图阿里Java开发手册中的说明,本文我来详细分析 MySQL EXPLAIN 中的type类型,并按照性能从优到劣排序:
📊MySQL EXPLAIN type 类型性能层级
🏆第1梯队:最优性能
1. system
- 表中只有一行数据(系统表)
- 这是最好的情况,但很少见
2. const
- 通过主键或唯一索引进行等值查询
- 最多只返回一条记录
- 示例:
WHERE id = 1(id是主键) - 优化阶段就能确定结果
🥈第2梯队:优秀性能
3. eq_ref
- 多表连接时,使用主键或唯一索引进行关联
- 对于前表的每一行,后表最多匹配一行
- 常见于
INNER JOIN中主键关联
4. ref
- 使用普通索引进行等值查询
- 可能返回多条记录
- 示例:
WHERE name = '张三'(name有普通索引)
🥉第3梯队:可接受性能
5. range
- 对索引进行范围扫描
- 示例:
WHERE id > 100、BETWEEN、IN等 - 比全表扫描好得多
⚠️第4梯队:需要优化
6. index
- 索引全扫描:扫描整个索引树
- 虽然比全表扫描快(因为索引通常比表小)
- 但仍然是线性扫描,性能较差
- 示例:
SELECT id FROM table(id是索引)
7. ALL
- 全表扫描
- 性能最差,需要扫描所有数据行
- 数据量大时非常缓慢
📈性能对比表
级别 | 扫描方式 | 性能 | 说明 -----------|------------------|----------|------------------- system | 系统表 | ★★★★★ | 只有一行 const | 主键/唯一索引等值 | ★★★★☆ | 最多一行 eq_ref | 主键关联 | ★★★★☆ | 连接优化 ref | 普通索引等值 | ★★★☆☆ | 推荐目标 range | 索引范围 | ★★☆☆☆ | 最低要求 index | 索引全扫描 | ★☆☆☆☆ | 需要优化(反例) ALL | 全表扫描 | ☆☆☆☆☆ | 必须优化🔍如何从 type 判断查询效率
✅好的情况:
- const/eq_ref:最优,秒级响应
- ref:良好,毫秒级响应
- range:可接受,数据量大时可能需要优化
❌差的情况:
- index:虽然比 ALL 好,但仍是线性扫描
- ALL:必须优化,否则会随数据量增长而急剧变慢
💡优化建议
1.至少达到 range 级别
-- 优化前:可能 type=ALLSELECT*FROMusersWHEREage>25;-- 优化后:type=range-- 给 age 字段添加索引CREATEINDEXidx_ageONusers(age);2.争取达到 ref 级别
-- 优化前:type=range(因为用了范围查询)SELECT*FROMordersWHEREuser_idIN(1,2,3);-- 如果业务允许,改为等值查询SELECT*FROMordersWHEREuser_id=1;3.尽可能达到 const
-- 使用主键或唯一索引SELECT*FROMusersWHEREid=1;SELECT*FROMusersWHEREemail='user@example.com';-- email需是唯一索引📝实际查询示例分析
-- 假设 users 表有:-- id (主键), name (普通索引), age (无索引), email (唯一索引)EXPLAINSELECT*FROMusersWHEREid=1;-- type: const ✓ (最优)EXPLAINSELECT*FROMusersWHEREemail='test@example.com';-- type: const ✓EXPLAINSELECT*FROMusersWHEREname='张三';-- type: ref ✓ (良好)EXPLAINSELECT*FROMusersWHEREage>25;-- type: ALL ✗ (需要给 age 加索引)EXPLAINSELECTidFROMusers;-- type: index ✗ (虽然只查索引列,但仍是全索引扫描)🎯总结关键点
- const > ref > range > index > ALL(性能递减)
- 目标:至少达到
range,争取达到ref,最好是const - index 类型并不好:虽然是扫描索引,但仍是线性扫描,特别是大数据表时要避免
- 优化手段:添加合适的索引、改写查询条件、避免全表扫描