EXPLAIN is used to obtain a query execution plan (that is, an explanation of how MySQL would execute a query).
EXPLAIN 工具能用于获取查询执行计划,即分析 MySQL 如何执行一个 SQL 语句。我们可以通过使用EXPLAIN 去模拟优化器执行 SQL 语句,从而分析 SQL 语句有没有使用索引、是否采用全表扫描方式、判断能否更进一步优化等。我们可以根据EXPLAIN 输出的数据来分析如何优化查询语句,提升查询语句的性能瓶颈。
如何使用 EXPLAIN ?
在 select
语句之前增加 explain
关键字即可使用EXPLAIN 工具。MySQL 会在查询上设置一个标记,此时,执行查询不会返回查询结果,而是返回执行计划的相关信息。如果查询语句的 from
中有子查询语句,依旧会执行这个子查询语句,结果会被放入临时表。
select
的序列号,查询语句中有几个 select
就会有多少个 id 列,一般来说 id
的顺序按 select 出现的顺序增加。序号越大表示该 select
的执行优先级越高,id
相同则按照列表顺序从上往下执行,若 id
为 NULL
,则最后执行。select
的查询类型,表示对应行是简单查询还是复杂查询,该类型的值如下表。最常见的几种类型:
union
。select
union
中的第二个和随后的select
from
子句中的子查询。MySQL 会将结果存放在一个临时表中,mysql 中也称为派生表(derived table),由子查询派生出来的表。select
,其不在 from 子句中。from
子句中存在子查询时,该列是 derivenN
格式的,表示当前查询依赖 id=N
的查询,会先执行 id=N
的查询。union
时,UNION RESULT 的 table 列的值为 union1,2
,1
和2
表示参与 union
的 select
行 id
。NULL
;反之则返回查询将访问的分区。
NULL
,这种情况是可能是查询表中只有少量数据,MySQL 认为全表查询比索引查询更快。
NULL
,则表明所有哦使用索引。我们可以使用 force index
来强制mysql 使用 possible_keys
列中的索引,或者通过 ignore index
忽略 possible_keys
列中的索引。
rows * filtered/100
估算出将要和 explain
中前一个表连接的行数(前一个表指 explain
中的 id
值比当前表 id
值小的表,id
值越小越先执行)。
explain extended
显示filtered
字段。explain
默认展示 filtered
字段。Using index
:表示使用覆盖索引,即 select
数据在索引信息中,不需要再查找读取其他值。Using filesort
:查询语句用外部排序(order by
),无法使用索引排序时。若数据较小,则从内存排序;否则需要在磁盘完成排序。这种情况下一般要尝试使用索引优化。Using index condition
:先按照条件过滤索引,找到符合索引条件的数据行,再用 where
子句条件中其他条件过滤数据行。即索引查询的列不能完全被索引覆盖。Using temporary
:当前查询语句需要创建一张临时表来保存数据,如果查询中有 group by
和 order by
子句(不同列)时可能会出现这种情况。而出现这种情况,我们也是需要对sql 语句进行优化,首先可以尝试建立索引来优化。Select tables optimized away
:结果集只有一行数据;得到该行数据需要计算一组确定的数据行。一般在使用某些聚合函数(max()、min())访问索引中的某个字段时出现。补充: Key_len 计算规则如下:
char(n)
和 varchar(n)
,在 mysql5.0.3 以后版本中,n
均代表字符数,而不是字节数。在 utf-8 编码格式下,一个数字或字母占 1 个字节,一个汉字占 3个字节。这两种占用字节分别计算如下:char(n)
:若是汉字,则长度就是 3n
字节;数字或字母则是 n
。varchar(n)
:若是汉字,则长度是 3n + 2
字节, 2 字节表示存储字符串的长度,因为 varchar
是变长字符串。数字或字母则是 n+2
。Tinyint
:1 字节Smallint
:2 字节Int
:4 字节Bigint
:8 字节 NULL
,需要 1 字节记录是否为 NULL
覆盖索引定义:mysql 执行计划 explain 结果里的 key 有使用索引,如果 select 后面查询的字段都可以从这个索引的树中获取,这种情况一般可以说是用到了覆盖索引,extra 里一般都有 using index;覆盖索引一般针对的是辅助索引,整个查询结果只通过辅助索引就能拿到结果,不需要通过辅助索引树找到主键,再通过主键去主键索引树里获取其它字段值