Mysql8 Explain优化字段说明
前言
mysql数据库查询优化,在达到一定数据量后是经常用到的,最优查询方式也会随着数据量的变化而变化,下面为通过翻译,查询整理而来。
id
id的编号是select的序列号,id也表示了select语句执行的优先级,id越大,执行的优先级就越高,id相同则从上到下依次执行,id为null的优先级最低;
select_type
simple
简单查询。查询不包含子查询和union
primary
复杂查询中最外层的 select
subquery
包含在 select 中的子查询(不在 from 子句中)
derived
包含在 from 子句中的子查询。查询结果存放在一个临时表中,也称为派生表;
table
当前正在查找哪张表
partitions
查询时匹配到的分区信息,对于非分区表值为NULL,当查询的是分区表时,partitions显示分区表命中的分区情况。
type
表示关联类型或者访问的类型,即MySQL决定如何查找表中的行,查找行记录的大致范围。从优到差的效率依次为:system>const>eq_ref>ref>range>index>all;
system
表中只有一条数据. 这个类型是特殊的 const 类型.
const
针对主键或唯一索引的等值查询扫描, 最多只返回一行数据. const 查询速度非常快, 因为它仅仅读取一次即可.
例如下面的这个查询, 它使用了主键索引, 因此 type 就是 const 类型的.
eq_ref
此类型通常出现在多表的 join 查询, 表示对于前表的每一个结果, 都只能匹配到后表的一行结果. 并且查询的比较操作通常是 =, 查询效率较高.
ref
此类型通常出现在多表的 join 查询, 针对于非唯一或非主键索引, 或者是使用了 最左前缀 规则索引的查询.
range
表示使用索引范围查询, 通过索引字段范围获取表中部分数据记录. 这个类型通常出现在 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN() 操作中.
当 type 是 range 时, 那么 EXPLAIN 输出的 ref 字段为 NULL, 并且 key_len 字段是此次查询中使用到的索引的最长的那个.
index
表示全索引扫描(full index scan), 和 ALL 类型类似, 只不过 ALL 类型是全表扫描, 而 index 类型则仅仅扫描所有的索引, 而不扫描数据.
index 类型通常出现在: 所要查询的数据直接在索引树中就可以获取到, 而不需要扫描数据. 当是这种情况时, Extra 字段 会显示 Using index.
ALL
表示全表扫描, 这个类型的查询是性能最差的查询之一. 通常来说, 我们的查询不应该出现 ALL 类型的查询, 因为这样的查询在数据量大的情况下, 对数据库的性能是巨大的灾难. 如一个查询是 ALL 类型查询, 那么一般来说可以对相应的字段添加索引来避免.
possible_keys
这一列表示Mysql分析查询可能会使用到的索引,但不是绝对的,这只是一个理论的分析,因为根据当前数据库数据量会自己选择最优索引
key
这一列表示Mysql实际采用哪个索引来优化对该表的访问,如果没有使用索引,则该列是 NULL。
key_len
这一列表示Mysql在索引中实际使用的字节数,可以通过这个值计算Mysql实际使用了那些索引。
注意:key_len只计算where条件中用到的索引长度,而排序和分组即便是用到了索引,也不会计算到key_len中。
key_len计算规则如下:
字符串
char(n): n 字节长度
varchar(n): 如果是 utf8 编码, 则是 3 n + 2字节; 如果是 utf8mb4 编码, 则是 4 n + 2 字节.
数值类型:
TINYINT: 1字节
SMALLINT: 2字节
MEDIUMINT: 3字节
INT: 4字节
BIGINT: 8字节
时间类型
DATE: 3字节
TIMESTAMP: 4字节
DATETIME: 8字节
字段属性: NULL 属性 占用一个字节. 如果一个字段是 NOT NULL 的, 则没有此属性.
ref
这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有如下
const
如果是使用的常数等值查询,
关联字段名
当关联查询时,会显示相应关联表的关联字段
func
如果查询条件使用了表达式、函数,或者条件列发生内部隐式转换
rows
这一列是mysql估计要查询出来结果需要读取并检测的行数,注意这个并不是最终要的结果集里的行数。这个值非常直观显示 SQL 的效率好坏, 原则上 rows 越少越好.
Fitered
filtered 这个是一个百分比的值,表里符合条件的记录数的百分比。简单点说,这个字段表示存储引擎返回的数据在经过过滤后,剩下满足条件的记录数量的比例。
在MySQL.5.7版本以前想要显示filtered需要使用explain extended命令。MySQL.5.7后,默认explain直接显示partitions和filtered的信息。
Extra
Using index
Mysql的执行计划中使用了索引,查询的结果可以从这个索引的索引树中获取,这种情况一般是使用了覆盖索引,覆盖索引一般针对的是辅助索引,查询通过辅助索引就可以得到想要的结果,不需要通过主键再去主键索引中查找,即不需要回表。速度不错
Using where
使用 where 语句来处理结果,并且查询的列未被索引覆盖
Using index condition
查询的列不完全被索引覆盖,where条件中是一个前导列的范围;
Using temporary
mysql需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的,首先是想到用索引来优化。
Using filesort
将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的。
Select tables optimized away
使用某些聚合函数(比如 max、min)来访问存在索引的某个字段。