执行计划
EXPLAIN
语句输出的各个列的作用:
列名 | 描述 |
---|---|
id |
在一个大的查询语句中每个SELECT 关键字都对应一个唯一的id
|
select_type |
SELECT 关键字对应的那个查询的类型 |
table |
表名 |
partitions |
匹配的分区信息 |
type |
针对单表的访问方法 |
possible_keys |
可能用到的索引 |
key |
实际上使用的索引 |
key_len |
实际使用到的索引长度 |
ref |
当使用索引列等值查询时,与索引列进行等值匹配的对象信息 |
rows |
预估的需要读取的记录条数 |
filtered |
某个表经过搜索条件过滤后剩余记录条数的百分比 |
Extra |
一些额外的信息 |
-
select
- 每一个表会有一条记录,如果是同一个select,那每个表的id一样。出现在前的为驱动表,后的为被驱动表
- 每一个select会有一个唯一的id(如果被优化成连接查询则另谈)
- 如果是union,会内部去重,通过生成临时表,所以会有一条临时表的记录,而union all则不需要
-
select_type
- simple:不包含子查询或者union的都是simple类型,包括连接查询
- primary:包含union、union all 或者子查询的外层查询或最左侧查询,则是primary
- union:除了最左侧查询,其他的都是union
- union_result:union去重的临时表查询
- subquery:如果包含子查询的语句不能转为semi-join,且是不相关子查询,那子查询的第一个select就是subquery,会被物化所以只执行一遍
- dependent_subquery:同上,如果是相关子查询,则是dependent_subquery,不会物化所以可能会执行多次
- dependent union:union或者union all中如果各个小查询都依赖于外层的话,除了最左边的小查询之外,其余的小查询都是dependent union
- derived:对于派生表被物化的,派生表对应的子查询就是derived
- materialized:如果物化之后与外层进行连接查询时,属性就是materialized
partitions:
-
type:代表的执行时的访问方法法:
system
,const
,eq_ref
,ref
,fulltext
,ref_or_null
,index_merge
,unique_subquery
,index_subquery
,range
,index
,ALL
system:当表中只有一条记录并且该表使用的存储引擎的统计数据是精确的,比如MyISAM、Memory,那么对该表的访问方法就是
system
eq_ref:通过主键或者唯一二级索引列等值匹配的方式进行访问的(如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较)与const的区别就是一个常数一个非常数
index_merge:
Intersection
、union
、sort-union
-
unique_subquery:包含IN的子查询,如果可以转换为EXISTS,且子查询可以使用主键进行等值匹配的话
EXPLAIN SELECT * FROM s1 WHERE key2 IN (SELECT id FROM s2 where s1.key1 = s2.key1) OR key3 = 'a';
index_subquery与unique_subquery类似,只是访问子查询中的表时使用的是普通索引
-
possible_keys和key
- possible_keys表示可能用到的索引,key表示实际用到的索引
- 如果用的是index方式,则不会显示possible_keys,只会显示真正用到的key
-
key_len:索引记录的最大长度
- 如果是固定长度,则是固定值,如果是变长,则是字符长度*字符所占的字节
- 如果可以存储NULL值,则key_len比不可以存储NULL值时多一个字节
- 对于变长字段,都会有2个字节的空间来存储该变长列的实际长度
ref:当访问方法是
const
、eq_ref
、ref
、ref_or_null
、unique_subquery
、index_subquery
其中之一时,ref
列展示的就是与索引列作等值匹配的东东是个啥,比如只是一个常数或者是某个列。rows:如果要用全表时,rows代表预计需要扫描的行数,如果使用索引来查询,就代表预计扫描的索引记录行数
filtered:被驱动表占驱动表条数的百分比
-
extra:代表的是额外的信息
SELECT * FROM s1 WHERE key1 > 'z' AND key1 LIKE '%a'; 这个查询虽然用到了key1的索引,但是like的后缀匹配用不了索引,所以正常需要查出前面的条件后回表然后进行过滤,但其实可以根据前面的条件查出的记录进行判断是否满足后面的条件,如果不满足可以直接不回表,减少随机IO。这就叫索引条件下推——Using index condition
-
查看执行计划的成本:
EXPLAIN FORMAT=JSON SELECT * FROM s1