MySQL优化 - EXPLAIN执行计划全解析
EXPLAIN是我们最常用的SQL分析工具,在使用工具之前我们需要先了解下工具中每一项代表的含义,如下是EXPLAIN中的所有列:mysql> explain select * from user u1 left join user u2 on u1.id=u2.id where u1.name='wyh';+----+-------------+-------+-----------...
EXPLAIN是MySQL中分析SQL执行效率、定位性能瓶颈的核心工具,它能模拟MySQL优化器的执行逻辑,输出SQL的执行计划详情,让我们清晰看到查询是否使用索引、走了哪个索引、是否全表扫描、表连接方式等关键信息。
优化SQL的前提是读懂执行计划,而EXPLAIN就是解读执行计划的唯一入口,本文将全面解析EXPLAIN的每一列含义,重点吃透优化中最需要关注的核心字段,让SQL优化有迹可循。
一、EXPLAIN基础使用
1. 使用语法
在需要分析的SELECT语句前直接添加EXPLAIN关键字即可,简单直接:
EXPLAIN + 待分析的SQL语句;
2. 执行示例
以下是多表关联查询的EXPLAIN执行结果,也是后续解析各字段的基础示例:
mysql> explain select * from user u1 left join user u2 on u1.id=u2.id where u1.name='wyh';
+----+-------------+-------+------------+--------+------------------+------------------+---------+----------------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+--------+------------------+------------------+---------+----------------+------+----------+-------+
| 1 | SIMPLE | u1 | NULL | ref | idx_name_address | idx_name_address | 1023 | const | 1 | 100 | NULL |
| 1 | SIMPLE | u2 | NULL | eq_ref | PRIMARY | PRIMARY | 8 | ssb_test.u1.id | 1 | 100 | NULL |
+----+-------------+-------+------------+--------+------------------+------------------+---------+----------------+------+----------+-------+
2 rows in set
3. 核心关注字段
EXPLAIN输出的所有列都有其意义,但实际优化中,抓住5个核心字段就能解决90%的性能问题,重点关注:
id:查询的执行顺序type:表的访问类型(核心中的核心,直接反映索引使用效率)possible_keys:查询可命中的索引集合key:优化器实际选中的索引(判断是否走对索引)Extra:额外执行信息(反映是否有文件排序、临时表等性能损耗)
二、EXPLAIN各字段详细解析
1. id - 查询执行顺序标识
id表示SQL中各查询操作的执行优先级,数值为数字,核心规则:
id越大,执行顺序越靠前(子查询的id通常大于外层查询,先执行子查询再执行外层)id相同,执行顺序从上到下(多表连接、同层级查询按结果集中的行序执行)
2. select_type - 查询类型
select_type用于区分普通查询、子查询、联合查询等不同的查询类型,核心标识查询的复杂程度,常见取值及含义:
SIMPLE:简单SELECT查询,查询中不包含子查询、UNION或其他复杂结构PRIMARY:查询中包含复杂子部分时,最外层的查询会被标记为该类型SUBQUERY:在SELECT子句或WHERE子句中直接包含的子查询DERIVED:在FROM子句中包含的子查询,MySQL会将其执行结果存入临时衍生表UNION:UNION关键字后第二个及之后的SELECT查询UNION RESULT:从UNION联合查询的结果集中获取最终数据的查询操作
3. table - 关联的表名
表示当前行的执行计划对应的数据表,取值为表名、表别名(如示例中的u1、u2),若为衍生表则会显示derived+数字(数字对应id)。
4. type - 表访问类型【核心】
type表示MySQL访问表中数据的方式,直接反映查询是否使用索引、使用的索引效率如何,是判断SQL性能的核心指标。type的性能从优到劣依次排序为:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
实际优化中,重点关注前7个常用等级,目标是至少优化到range级别,最好达到ref或eq_ref级别,常见核心取值及含义:
system:特殊的const类型,表中只有一行数据(如系统表),性能最优const:通过主键/唯一索引一次匹配到唯一行数据,MySQL会将其转换为常量处理,查询极快eq_ref:多表连接时,通过主键/唯一索引关联,被连接表的每一行都只匹配一行结果,性能仅次于constref:通过非唯一索引进行数据查询,匹配到多行符合条件的数据,是单表查询中较优的级别range:使用索引进行范围查询(如>、<、IN、BETWEEN等),仅扫描索引范围内的数据index:扫描整个索引树获取数据,未回表但扫描了全部索引,性能远差于rangeALL:全表扫描,未使用任何索引,扫描表中所有数据,性能最差,需坚决优化
5. possible_keys - 可命中的索引集合
表示当前查询理论上可以使用的所有索引,MySQL优化器会从该集合中筛选出最优索引作为实际执行的索引。
该字段仅为候选索引参考,不代表实际使用,若字段值为NULL,表示查询无可用索引。
6. key - 实际使用的索引【核心】
表示MySQL优化器最终选中执行查询的索引,是判断查询是否真正走索引的关键依据。
- 若字段值为
NULL,表示查询未使用任何索引(大概率是全表扫描ALL) - 若需强制MySQL使用/忽略候选索引,可使用
FORCE INDEX、USE INDEX、IGNORE INDEX关键字指定
7. key_len - 索引使用的字节长度
表示查询中实际使用的索引字段字节数,可通过该字段判断索引的使用程度(是否使用了复合索引的所有列)。
核心特点:
key_len是根据表定义计算的理论最大长度,非实际数据的使用长度- 优化原则:在不损失查询精度的前提下,
key_len越短越好,索引使用效率更高
8. ref - 索引关联的列/常量
表示查询中用于匹配索引的列名或常量,反映索引与其他数据的关联方式,常见取值:
const:使用常量值匹配索引(如示例中的name='wyh')- 表名/列名:多表连接时,使用其他表的列值匹配索引(如示例中的
ssb_test.u1.id) NULL:未使用索引关联,直接扫描
9. rows - 预估扫描行数
表示MySQL根据表统计信息和索引使用情况,预估需要扫描的行数,用于判断查询的大致数据量。
核心说明:
- 该值为预估数值,非实际扫描的精确行数
- 优化原则:行数越少越好,扫描行数越少,查询效率越高
10. filtered - 结果过滤比例
表示通过WHERE条件过滤后,符合查询条件的记录占扫描行数的比例,取值范围0-100(百分比)。
- 数值越接近100,说明过滤效果越好,无用数据扫描越少
- 数值越低,说明大部分扫描的行都不符合条件,查询的过滤条件设计不合理
11. Extra - 额外执行信息【核心】
Extra包含了不适合在其他列展示,但对性能至关重要的额外执行信息,是定位隐性性能问题的关键,常见核心取值及含义:
Using filesort:MySQL无法利用索引完成排序,需进行外部文件排序,性能损耗大,必须优化Using temporary:查询过程中创建了临时表,常见于ORDER BY和GROUP BY,性能损耗大,需优化Not exists:MySQL对LEFT JOIN的优化策略,找到匹配行后立即停止扫描,属于优化项Using index:使用了覆盖索引,直接从索引中获取所有查询数据,无需回表,性能最优Using index condition:MySQL5.6新增的索引条件推送特性,可在二级索引上执行部分过滤条件,减少回表IO,属于优化项Using where:MySQL将存储引擎返回的数据在服务层进行WHERE条件过滤,说明存储引擎未完成全部过滤Using join buffer:多表连接时使用了连接缓存,说明连接条件未使用索引,需优化Impossible where:WHERE子句的条件永远为false,无法查询到任何数据(如非空列执行is null)NULL:无特殊额外信息,查询执行流程正常
三、EXPLAIN优化核心原则
- 优先保证
type字段至少达到range级别,杜绝index和ALL(全表扫描/全索引扫描) - 确保
key字段非NULL,查询必须走有效索引,避免索引失效 - 坚决杜绝
Extra字段出现**Using filesort和Using temporary**,这两个是性能优化的重灾区 - 尽可能让
rows预估扫描行数最小化,减少数据扫描量 - 利用
Using index覆盖索引优化,避免回表查询,大幅提升查询效率 - 若
possible_keys有值但key为NULL,说明索引失效,需排查索引使用条件(如字段类型不匹配、使用函数等)
更多推荐

所有评论(0)