它不仅能够揭示SQL语句的执行路径、索引使用情况及资源消耗模型,更是诊断慢查询和优化索引策略的核心工具
本文将深度解析EXPLAIN执行计划的机制与实践技巧,助您全面掌握SQL性能调优的艺术
一、EXPLAIN执行计划概览 EXPLAIN是MySQL提供的一个强大的SQL分析指令
通过在SELECT语句前添加EXPLAIN关键字(或使用EXPLAIN FORMAT=JSON获取详细报告),MySQL会模拟优化器生成执行计划,而不实际执行查询
这一特性使得EXPLAIN成为分析SQL性能、优化查询策略的理想工具
EXPLAIN执行计划的核心价值在于: - 执行路径可视化:展示表的读取顺序、访问方法及连接方式,帮助开发者直观理解查询的执行流程
- 索引有效性分析:揭示可能使用与实际使用的索引,为索引优化提供直接依据
- 资源消耗预估:通过扫描行数和过滤比例预判性能瓶颈,为性能调优提供数据支持
- 执行策略诊断:识别全表扫描、临时表、文件排序等危险操作,指导优化方向
二、EXPLAIN执行计划详解 EXPLAIN执行计划的结果通常包含多个关键字段,每个字段都承载着优化器决策的关键信息
以下是对这些字段的深度解析: 1.id:SELECT查询的序列号,表示查询中执行select子句或顺序表操作的顺序
id值越大,优先级越高,越先被执行;id值相同,则从上往下依次执行;id列为NULL,表示这是一个结果集,不需要使用它来进行查询
2.select_type:查询的类型,主要用于区分普通查询、联合查询、子查询等复杂查询
- SIMPLE:简单查询,不包含UNION操作或子查询,位于最外层的查询
- PRIMARY:需要UNION操作或含有子查询的SELECT,位于最外层的查询
- DERIVED:FROM列表中出现的子查询,也叫做衍生表
MySQL递归执行这些子查询,把结果放在临时表里
- SUBQUERY:除了FROM子句中包含的子查询外,其他地方出现的子查询
- UNION:若第二个SELECT出现在UNION之后,则被标记为UNION
- UNION RESULT:从UNION表获取结果的SELECT,因为它不需要参与查询,所以id字段为NULL
3.table:表示EXPLAIN的一行正在访问哪个表
如果查询使用了别名,这里显示的是别名;如果不涉及对数据表的操作,则显示为NULL;如果显示为尖括号括起来的
4.type:访问类型,即MySQL决定如何查找表中的行 这是性能优化的核心指标,依次从好到差为:system > const > eq_ref > ref > range > index > ALL
- system:表中只有一条元组匹配(等于系统表),这是const类型的特例,平时不会出现
- const:通过索引一次就找到了,表示使用主键索引或者唯一索引
- eq_ref:主键或者唯一索引中的所有字段被用于连接使用,只会返回一行匹配的数据
- ref:普通索引扫描,可能返回多个符合查询条件的行
- range:索引范围扫描,常见于使用>,<,between,in,like等运算符的查询中
- index:索引全表扫描,把索引树从头到尾扫描一遍 虽然比ALL快,但仍需优化
- ALL:遍历全表以找到匹配的行,是性能最差的访问类型,必须优化
5.possible_keys:显示查询可能使用到的索引
6.key:实际使用的索引 当select_type为index_merge时,这里可能出现两个以上的索引;其他的select_type这里只会出现一个索引
7.key_len:实际上用于优化查询的索引长度,即索引中使用的字节数 通过这个值,可以计算出一个多列索引里实际使用了哪些字段 key_len的计算规则复杂,需考虑字段是否为NULL、索引的最大长度限制等因素
8.ref:显示哪个字段或者常量与key一起被使用 如果是使用的常量等值查询,这里会显示const;如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段;如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func
9.rows:MySQL根据表统计信息及索引选用情况,大致估算此处查询需要读取的行数(不是精确值) 这个值对于评估查询效率具有重要意义
10.filtered:表示存储引擎返回数据后,WHERE子句过滤的剩余百分比 理想值为100%,表示索引完全覆盖WHERE条件;低于10%则表示严重过滤失效,需优化索引
11.Extra:展示一些额外信息,同样十分重要 例如,“Using where”表示该查询使用了WHERE条件;“Using index”表示查询仅通过索引即可满足需求,无需访问数据表,即覆盖索引
三、EXPLAIN执行计划实践技巧
1.索引优化最佳实践
- 最左前缀法则:对于复合索引,查询条件应包含索引的最左前缀字段,以充分利用索引
- 覆盖索引:通过创建覆盖索引,避免回表操作,提高查询效率
- 索引下推:利用MySQL 5.6及以上版本的索引下推功能,减少IO操作,提升查询性能
2.避免索引失效的隐蔽陷阱
- 隐式编码转换:确保查询条件中的字段编码与索引编码一致,避免索引失效
- 函数计算索引列:避免在索引列上进行函数计算或表达式运算,否则索引将失效
- OR条件未覆盖:对于包含OR条件的查询,应确保所有涉及的字段都有索引,否则可能导致全表扫描
3.高级应用技巧
- 扩展EXPLAIN方法:利用MySQL 8.0及以上版本的EXPLAIN ANALYZE和EXPLAIN FORMAT=TREE功能,获取更详细的执行计划和执行时间统计
- JSON格式深度分析:使用EXPLAIN FORMAT=JSON获取执行计划的JSON格式输出,进行深度分析
- 优化大数据量分页查询:通过覆盖索引和子查询优化大数据量分页查询,减少扫描行数,提高查询效率
四、避坑指南与最佳实践
1.统计信息时效性:定期执行ANALYZE TABLE更新统计信息,确保优化器能够基于最新的统计信息进行决策
2.索引维护代价:写密集型表的每个索引都会增加20%-30%的写开销,需平衡读写需求,合理设计索引
3.优化器版本差异:不同版本的MySQL优化器可能存在差异,应了解并充分利用当前版本的优化特性
4.执行计划局限性:EXPLAIN执行计划不显示存储过程或触发器内的查询,