EXPLAIN语句输出的各个列解释

#EXPLAIN语句输出的各个列解释#select_type

每一个SELECT关键字代表的小查询都定义了一个称之为select_type的属性,意思是我们只要知道了某个小查询的select_type属性,就知道了这个小查询在整个大查询中扮演了一个什么角色

#SIMPLE

查询语句中不包含UNION或者子查询的查询都算作是SIMPLE类型,连接查询也算是SIMPLE类型。

#PRIMARY

对于包含UNION、UNIONALL或者子查询的大查询来说,它是由几个小查询组成的,其中最左边的那个查询的select_type值就是PRIMARY

#UNION

对于包含UNION或者UNIONALL的大查询来说,它是由几个小查询组成的,其中除了最左边的那个小查询以外,其余的小查询的select_type值就是UNION

#UNIONRESULT

MySQL选择使用临时表来完成UNION查询的去重工作,针对该临时表的查询的select_type就是UNIONRESULT,例子上边有,就不赘述了。

#SUBQUERY

如果包含子查询的查询语句不能够转为对应的semi-join的形式,并且该子查询是不相关子查询,并且查询优化器决定采用将该子查

询物化的方案来执行该子查询时,该子查询的第一个SELECT关键字代表的那个查询的select_type就是SUBQUERY

#DEPENDENTSUBQUERY

如果包含子查询的查询语句不能够转为对应的semi-join的形式,并且该子查询是相关子查询,则该子查询的第一个SELECT关键字代表的那个查询的select_type就是DEPENDENTSUBQUERY

#DEPENDENTUNION

在包含UNION或者UNIONALL的大查询中,如果各个小查询都依赖于外层查询的话,那除了最左边的那个小查询之外,其余的小查询的select_type的值就是DEPENDENTUNION

#DERIVED

对于采用物化的方式执行的包含派生表的查询,该派生表对应的子查询的select_type就是DERIVED

#MATERIALIZED

当查询优化器在执行包含子查询的语句时,选择将子查询物化之后与外层查询进行连接查询时,该子查询对应的select_type属性就是MATERIALIZED

#UNCACHEABLESUBQUERY

不常用,就不多唠叨了。

#UNCACHEABLEUNION

不常用,就不多唠叨了。

#type

执行计划的一条记录就代表着MySQL对某个表的执行查询时的访问方法

system:当表中只有一条记录并且该表使用的存储引擎的统计数据是精确的,比如MyISAM、Memory,那么对该表的访问方法就是system。

const:根据主键或者唯一二级索引列与常数进行等值匹配

eq_ref:在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的(如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较),则对该被驱动表的访问方法就是eq_ref

ref:搜索条件为二级索引列与常数等值比较来定位多条记录,采用二级索引来执行查询的访问方法

fulltext全文索引

ref_or_null:当对普通二级索引进行等值匹配查询,该索引列的值也可以是NULL值时,那么对该表的访问方法就可能是ref_or_null

index_merge:一般情况下对于某个表的查询只能使用到一个索引,但我们唠叨单表访问方法时特意强调了在某些场景下可以使用Intersection、Union、Sort-Union这三种索引合并的方式来执行查询,会使用到多个索引。

unique_subquery:类似于两表连接中被驱动表的eq_ref访问方法,unique_subquery是针对在一些包含IN子查询的查询语句中,如果查询优化器决定将IN子查询转换为EXISTS子查询,而且子查询可以使用到主键进行等值匹配的话,那么该子查询执行计划的type列的值就是unique_subquery

index_subquery:index_subquery与unique_subquery类似,只不过访问子查询中的表时使用的是普通的索引(unique_subquery之前用的是主键索引或者一二级索引)。

range:如果使用索引获取某些范围区间的记录,那么就可能使用到range访问方法

index:当我们可以使用索引覆盖,但需要扫描全部的索引记录时,该表的访问方法就是index。

ALL:全表扫描。

#possible_keys和key

possible_keys列表示在某个查询语句中,对某个表执行单表查询时可能用到的索引有哪些,key列表示实际用到的索引有哪些。

#key_len

key_len列表示当优化器决定使用某个索引执行查询时,该索引记录的最大长度,它是由这三个部分构成的:

对于使用固定长度类型的索引列来说,它实际占用的存储空间的最大长度就是该固定值,对于指定字符集的变长类型的索引列来说,比如某个索引列的类型是VARCHAR(),使用的字符集是utf8,那么该列实际占用的最大存储空间就是×3=个字节。

如果该索引列以存储NULL值,则key_len比不可以存储NULL值时多1个字节。

对于变长字段来说,都会有2个字节的空间来存储该变长列的实际长度。

例子

提示:有的同学可能有疑问:你在前边唠叨InnoDB行格式的时候不是说,存储变长字段的实际长度不是可能占用1个字节或者2个字节么?为什么现在

不管三七二十一都用了2个字节?这里需要强调的一点是,执行计划的生成是在MySQLserver层中的功能,并不是针对具体某个存储引擎的功能,设计

MySQL的大叔在执行计划中输出key_len列主要是为了让我们区分某个使用联合索引的查询具体用了几个索引列,而不是为了准确的说明针对某个具体

存储引擎存储变长字段的实际长度占用的空间到底是占用1个字节还是2个字节

#ref#rows

如果查询优化器决定使用全表扫描的方式对某个表执行查询时,执行计划的rows列就代表预计需要扫描的行数,如果使用索引来执行查询时,执行计划的rows列就代表预计扫描的索引记录行数

#filtered

之前在分析连接查询的成本时提出过一个conditionfiltering的概念,就是MySQL在计算驱动表扇出时采用的一个策略:

如果使用的是全表扫描的方式执行的单表查询,那么计算驱动表扇出时需要估计出满足搜索条件的记录到底有多少条。

如果使用的是索引执行的单表扫描,那么计算驱动表扇出的时候需要估计出满足除使用到对应索引的搜索条件外的其他搜索条件的记录有多少条。

连接查询中驱动表对应的执行计划记录的filtered值,比方说下边这个查询:

从执行计划中可以看出来,查询优化器打算把s1当作驱动表,s2当作被驱动表。我们可以看到驱动表s1表的执行计划的rows列为,filtered列为10.00,这意味着驱动表s1的扇出值就是×10.00%=.8,这说明还要对被驱动表执行大约次查询。

Extra列是用来说明一些额外信息的,我们可以通过这些额外信息来更准确的理解MySQL到底将如何执行给定的查询语句

欢迎


转载请注明:http://www.aierlanlan.com/cyrz/7142.html

  • 上一篇文章:
  •   
  • 下一篇文章: