一、explain作用
MySQL的EXPLAIN命令是开发者经常使用的一个强大的分析工具,帮助开发者了解查询的性能瓶颈和优化方向。
二、使用方法
只需要在要执行的sql语句前加explain关键字即可,如下
mysql> explain select * from user where id >60;
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | SIMPLE | user | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 40 | 100.00 | Using where |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
三、explain执行结果分析
id:表示查询的顺序,数字越小优先级越高。
select_type:表示查询的类型
-
SIMPLE:表示简单查询,即不包含子查询或 UNION 操作的查询。
-
PRIMARY:表示主查询,即外层查询。
-
SUBQUERY:表示子查询中的第一个 SELECT 语句。
-
DERIVED:表示派生表的查询,即子查询中除第一个 SELECT 语句之外的其他 SELECT 语句。
-
UNION:表示 UNION 操作的结果集。
-
UNION RESULT:表示 UNION 操作的结果集,与 UNION 类似,但只能用于 MySQL 数据库。
-
TABLE:表示查询结果是一个表,而不是一个具体的值。
例如:如果发现查询的类型一个简单的查询,可以考虑添加索引来提高查询性能;如果发现查询包含子查询,那么可以考虑将子查询转换为连接查询来提高性能。总之,select_type
字段的分析对于优化 SQL 查询具有重要的指导意义。
table:表示查询涉及的表名。
table
字段表示查询涉及的表名。在 SQL 查询中,可能会涉及到多个表的连接操作,而 table 字段则用于显示这些表的名称。
+----+-------------+-------+------+---------------+------+---------+------+------+----------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------+
| 1 | SIMPLE | users | ALL | NULL | NULL | NULL | NULL | 1 | NULL |
| 1 | SIMPLE | orders| ref | user_id | user_id | 4 | func | 1 | NULL |
+----+-------------+-------+------+---------------+------+---------+------+-----
type:表示数据访问类型,如 ALL(全表扫描)、index(索引扫描)、range(范围扫描)等。不同的访问类型对性能的影响不同,通常 ALL 类型的访问性能最差,而 index 和 range 类型的访问性能较好。
-
ALL:表示全表扫描,即需要遍历整个表来查找数据。这种类型的查询性能最差,通常需要优化。
-
index:表示使用索引进行访问,不需要遍历整个表。这种类型的查询性能较好,但需要注意索引的选择和使用。
-
range:表示使用范围查询,即在索引上进行范围查找。这种类型的查询性能较好,但需要注意索引的选择和使用。
-
ref:表示使用非唯一索引进行等值查询。这种类型的查询性能较好,但需要注意索引的选择和使用。
-
eq_ref:表示使用唯一索引进行等值查询。这种类型的查询性能最好,因为只需要查找一个记录即可。
-
const、system:这两种类型的查询性能都非常好,因为它们只需要查找一个常量或者系统表中的记录。
-
NULL:表示使用 IS NULL 或 IS NOT NULL 进行查询。这种类型的查询性能较好,但需要注意索引的选择和使用
例如,如果发现查询使用了 ALL 类型的访问,那么可以考虑添加索引来提高查询性能;如果发现查询使用了 Using filesort,那么可以考虑调整排序方式以提高性能
possible_keys:表示可能使用的索引。
mysql> explain select * from user where age >18 and sex="男";
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | user | NULL | ALL | idx_age_sex | NULL | NULL | NULL | 100 | 49.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
key:表示实际使用的索引。如果实际使用的索引与可能使用的索引不一致,可能需要调整索引以提高查询性能。
mysql> explain select * from user where age = 18;
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | user | NULL | ref | idx_age_sex | idx_age_sex | 5 | const | 2 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+-------------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
key_len:表示使用的索引的长度。长度越短,表示索引越高效。
key_len
的值反映了在执行查询时,所使用的索引中涉及到的字段的总长度。这个长度越短,通常意味着索引的效率越高,因为数据库在查找索引时需要读取的数据量更少。在联合索引中,key_len
还可以帮助我们判断有多少列被用于索引查找。如果 key_len
较短,可能意味着只有部分列被用作过滤条件,而不是所有列都被使用。
key_len 的指导意义在于帮助我们了解索引的使用效率和查询的性能瓶颈。
-
优化索引结构:如果发现
key_len
过长,可能需要考虑调整索引结构,比如减少联合索引中的列数,或者选择更短的列作为索引。 -
评估查询性能:较短的
key_len
通常意味着查询性能更好,因为它减少了磁盘I/O操作的次数。相反,较长的key_len
可能意味着查询需要更多的磁盘读取,从而影响性能。 -
分析索引覆盖:通过
key_len
我们可以推断出是否发生了索引覆盖读(covering index),即查询所需的所有数据都包含在索引中,而不需要回表查询原始数据行。
ref:提供了关于如何利用索引进行查找的信息。
-
const: 表示该列被用作常量比较,即该列的值在索引中是唯一的或者是一个范围的最左端点。
-
eq_ref: 表示使用等于条件(=)来查找唯一索引的列,通常用于主键或唯一索引的查找。
-
range: 表示使用范围条件(如 <, >, BETWEEN)来查找索引列。
-
ref: 表示非唯一索引的列被用作查找条件,这通常是普通的比较操作,比如 = 或 <>。
-
fulltext: 表示使用全文索引进行查找。
-
ref_or_null: 类似于 ref,但是允许索引列的值为 NULL。
-
index_merge: 表示查询优化器使用了多个单个索引的合并来执行查询。
-
unique_subquery: 表示在子查询中使用了唯一索引。
-
index_subquery: 表示在子查询中使用了非唯一索引。
-
range_check: 表示对一个范围条件进行了检查,这通常发生在多列索引的情况下,其中一些列使用了范围条件,而其他列则没有。
ref
字段显示为 ALL
或 USING where
,这意味着查询没有使用索引,而是进行了全表扫描
rows:表示估计需要检查的行数。这个数字越大,表示查询性能可能越低。
rows
字段表示查询执行过程中预计需要扫描的行数。这个值是一个估计值,用于帮助我们评估查询的性能和优化查询。较高的 rows
值通常意味着查询性能较差,因为需要读取更多的数据行。相反,较低的 rows
值通常意味着查询性能较好,因为只需要读取较少的数据行。
Extra:表示额外的信息,如 Using index(使用覆盖索引)、Using filesort(使用文件排序)等。这些信息可以帮助我们了解查询的性能瓶颈并进行优化。
-
Using index: 表示查询使用了覆盖索引(covering index),即查询所需的所有数据都包含在索引中,而不需要回表查询原始数据行。
-
Using where: 表示查询使用了 WHERE 子句进行过滤,但并没有使用到索引。这通常意味着查询进行了全表扫描。
-
Using filesort: 表示查询需要进行排序操作,这通常发生在 ORDER BY 子句中。如果需要排序的数据量较大,可能会影响查询性能。
-
Using temporary: 表示查询需要创建临时表来存储中间结果。这通常发生在复杂的查询或聚合操作中,如 GROUP BY 或 DISTINCT。
-
Using index condition: 表示查询使用了索引条件推送(Index Condition Pushdown),即在索引层就进行了条件过滤,减少了需要回表的数据行数。
-
Using intersect(...): 表示查询使用了集合交操作,这通常发生在多表查询中,如 JOIN 或 UNION。
-
Using union(...): 表示查询使用了集合并操作,这通常发生在多表查询中,如 JOIN 或 UNION。
-
Using sort_union(...): 表示查询使用了排序合并连接(Sort-Merge Join),这通常发生在多表查询中,特别是在没有合适索引的情况下。
-
Using where; Using index: 表示查询既使用了 WHERE 子句进行过滤,又使用了覆盖索引。
-
Using index for group-by: 表示查询使用了索引进行分组操作,这通常发生在 GROUP BY 子句中。
-
Using unique index: 表示查询使用了唯一索引进行查找。
-
Using on-disk sort: 表示查询需要在磁盘上进行排序操作,这通常发生在内存中无法容纳所有需要排序的数据时。