它不仅能够帮助开发者深入了解SQL查询的执行计划,还能精准定位性能瓶颈,从而指导我们进行针对性的优化
本文将全面解析MySQL EXPLAIN命令的各项参数,通过实例展示其使用方法,并深入探讨如何利用这些信息进行高效的数据库性能调优
一、EXPLAIN命令简介 EXPLAIN是MySQL提供的一个性能分析工具,它允许开发者在不实际执行SQL查询的情况下,查看查询的执行计划
通过模拟查询过程,EXPLAIN返回一个详细的表格,展示了索引使用、表连接方式、扫描行数等关键信息
这些信息对于诊断性能瓶颈、优化查询性能至关重要
二、EXPLAIN命令输出参数详解 1.id:查询的标识符,用于表示查询中SELECT子句或操作表的顺序
- 如果id相同,表示这些操作是同一查询的一部分,执行顺序从上到下
- 如果id不同,id值越大,优先级越高,越先执行
- 特殊值:NULL表示是其他查询的合并结果(如UNION)
2.select_type:表示SELECT查询的类型
- SIMPLE:简单的SELECT查询,不包含子查询或UNION
- PRIMARY:最外层的SELECT查询(在包含子查询或UNION时)
- SUBQUERY:子查询中的第一个SELECT(不在FROM子句中)
- DERIVED:派生表(FROM子句中的子查询)
- UNION:UNION中的第二个或后续的SELECT查询
- UNION RESULT:UNION的结果集
3.table:表示当前查询涉及的表名或别名
- 对于派生表(DERIVED),会显示派生表的名称(通常是子查询的编号)
- 对于临时表,可能会显示“temporary”
4.partitions:表示查询访问的分区(如果表是分区表)
- 值:分区名列表,如果没有分区则为NULL
5.type:访问类型,是EXPLAIN中最重要的列之一,反映了查询的效率
- system:表只有一行(系统表),这是const的特例
- const:通过索引一次就找到了,用于比较PRIMARY KEY或UNIQUE索引
因为只匹配一行数据,所以很快
-eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配
常见于主键或唯一索引的连接查询
- ref:非唯一性索引扫描,返回匹配某个单独值的所有行
本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以它应该属于查找和扫描的混合体
- range:只检索给定范围的行,使用一个索引来选择行
key列显示使用了哪个索引
一般就是在你的where语句中出现了between、<、>、in等的查询
- index:Full Index Scan,Index与All区别为index类型只遍历索引树
这通常比ALL快,因为索引文件通常比数据文件小
也就是说虽然all和index都是读全表,但index是从索引中读取的,而all是从硬盘中读的
- ALL:Full Table Scan,即全表扫描,意味着MySQL必须扫描整张表来找到需要的行
6.possible_keys:表示查询可能使用的索引
- 值:索引名列表,如果没有可能的索引则为NULL
注意:这只是MySQL认为可能使用的索引,实际执行时可能不会使用这些索引
7.key:表示查询实际使用的索引
- 值:索引名,如果没有使用索引则为NULL
注意:如果key为NULL,表示没有使用任何索引
8.key_len:表示使用的索引的长度(字节数)
- 值:数字,表示索引使用的字节数
可以通过这个值估算出使用了多少列
对于字符串类型,key_len的计算方式是:字符集的每个字符占用的字节数×字符串长度+可能的额外字节(如NULL终止符)
对于数字类型,key_len是固定的
9.ref:表示索引的哪一列被使用了,或者常量被用于比较
- 如果是const,表示使用了常量值
- 如果是列名,表示使用了该列的值进行比较
- 如果是NULL,表示没有使用引用
10. rows:表示MySQL认为必须检查的行数
- 值:数字,表示估计需要检查的行数
这是一个估计值,不是精确值
值越小,查询效率越高
11. filtered:表示存储引擎返回的数据在server层过滤后,剩余的数据的百分比
- 值:百分比(0-100)
这个值可以帮助你理解查询的过滤效率
值越高,表示过滤效果越好
12. Extra:包含额外的信息,对查询优化非常有用
- Using index:表示使用了覆盖索引(查询的列都在索引中,不需要回表)
- Using where:表示使用了WHERE条件过滤
- Using join buffer:表示使用了连接缓存(通常出现在没有使用索引的连接查询中)
- Using temporary:表示使用了临时表(通常出现在GROUP BY或ORDER BY中使用了非索引列时)
- Using filesort:表示使用了文件排序(通常出现在ORDER BY使用了非索引列时)
- Using index condition:表示使用了索引条件下推(ICP,MySQL 5.6+的特性)
- Using sort_union/Using union/Using intersect:表示使用了索引合并优化
三、如何使用EXPLAIN命令进行优化 1.识别全表扫描:通过检查type列,如果发现值为ALL,表示进行了全表扫描
这通常是性能瓶颈所在,需要考虑添加合适的索引来优化查询
2.检查索引使用:通过key列和possible_keys列,可以检查查询是否使用了预期的索引
如果key列为NULL,而possible_keys列有值,说明索引未被使用,需要调整查询条件或索引设计
3.优化排序和分组:如果Extra列出现Using temporary或Using filesort,表示查询中使用了临时表或外部排序
这通常发生在ORDER BY或GROUP BY子句使用了非索引列时
优化方法是考虑在这些列上添加索引
4.减少扫描行数:通过rows列可以预估查询需要检查的行数
如果行数过大,说明查询效率不高,需要优化索引或查询条件以减少扫描行数
5.利用覆盖索引:当Extra列出现Using index时,表示查询使用了覆盖索引,这是非常高效的查询方式
应尽量设计覆盖索引以减少回表查询的次数
6.分析复杂查询:对于包含子查询、JOIN操作等复杂查询,可以通过EXPLAIN的输出分析各部分的执行计划,找出性能瓶颈并进行优化
四、实战示例 以下是一个使用EXPLAIN命令优化查询性能的实战示例: 假设有一个users表和orders表,我们需要查询年龄大于30岁的用户的订单信息,并按用户名排序
原始查询语句如下: EXPLAIN SELECT - FROM users JOIN orders ON users.id = orders.user_id WHERE users.age > 30 ORDER BY users.name; 执行EXPLAIN后,我们得到如下输出: (注:以下输出为示例,实际输出可能因数据库版本和数据分布而异) +----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+ | id | select_type | table | partitions | type | possible_keys | key |key_len | ref | rows | filtered | Extra | +----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+ | 1 | SIMPLE | users | NULL | range | PRIMARY,age | age | 4 | NULL | 100 | 10.00 | Using where; Using