目录
explain执行计划
explain语法
表格形式输出
explain SQL语句;
两列形式输出
explain SQL语句\G
explain输出格式解释
输出列简介
列 | 意义 |
---|---|
id | 选择标识列 |
select_type | 这个查询的类型 |
table | 输出行的表 |
parpartitions | 匹配分区 |
type | 连接类型 |
possible_keys | 要选择的可能索引 |
key | 实际选择的索引 |
key_len | 所选键的长度 |
ref | 列与索引的比较 |
rows | 待审查行的估计 |
filtered | 按表条件筛选的行百分比 |
Extra | 补充资料 |
id
选择标识列:表示查询语句执行的优先级,相同的数字,从上往下执行,数字不同时值越大优先级越高.
选择标识列.这是查询中SELECT的顺序编号.如果该行引用其他行的联合结果.则该值可以为Null.在这种情况下,表列显示一个类似于<unionM,N>的值,以指示该行引用了id值为M和N的行的并集.
select_type
SELECT的类型,可以是下表中显示的任意类型.
select_type 值 | 意义 |
---|---|
SIMPLE | 简单查询(不使用UNION或子查询) |
PRIMARY | 最外层SELECT |
UNION | UNION中的第二个或更高版本SELECT语句 |
DEPENDENT UNION | UNION中的第二个或更高版本SELECT语句,依赖于外部查询. |
UNION RESULT | UNION的结果 |
SUBQUERY | 第一SELECT子查询 |
DEPENDENT SUBQUERY | 第一SELECT子查询,依赖于外部查询 |
DERIVED | 导出表,衍生表 |
DEPENDENT DERIVED | 依赖于另一个表的派生表 |
MATERIALIZED | 物化子查询 |
UNCACHEABLE SUBQUERY | 不能缓存结果的子查询,必须对外部查询的每一行进行重新计算 |
UNCACHEABLE UNION | 属于不可缓存子查询的UNION中的第二个或更高版本的SELECT |
DEPENDENT
通常表示相关子查询的使用.
什么是外部查询?
比方说这个sql语句吧:select (select t2.name from t2 where t2.did=t1.did) from t1
()里面的select t2.name from t2 where t2.did=t1.did就是inner outer.
而()外面的select (select t2.name from t2 where t2.did=t1.did) from t1 就属于outer query(外部查询).
table
输出行所引用的表的名称.这也可以是下列值之一:
<union
::该行指的是ID值为M和N的行的并集.M
,N
><derived
::该行引用id值为N的行的派生表结果,例如,派生表可能来自FROM子句中的子查询.N
><subquery
::该行引用id值为N的行的物化子查询的结果.N
>
parpartitions
查询将从其中匹配记录的分区.对于非分区表,该值为Null.
type
连接类型/访问类型.EXPLAIN输出的type列描述表是如何连接的.下面的列表描述了从最佳类型到最差类型排序的连接类型:
连接类型 | 意义 |
---|---|
system | 这个表只有一行(=system表).这是Const联接类型的特例. |
const | 该表最多有一个匹配行,在查询开始时读取.由于只有一行,因此行中列的值可以被优化器的其余部分视为常量.Const表非常快,因为它们只读取一次.const用于将 "主键" 或 "唯一" 索引的所有部分与常量值进行比较 |
eq_ref | 读取本表中和关联表表中的每行组合成的一行.除了系统和Const类型之外,这是最佳的连接类型.当连接使用索引的所有部分时,当索引是主键或唯一的非空索引时,使用它. |
ref | 所有具有匹配索引值的行都会从此表中读取前几个表中的每个行的组合.如果联接只使用键的最左前缀,或者键不是主键或唯一索引(换句话说,如果联接不能根据键值选择单个行),则使用ref.如果所使用的键只匹配几行,则这是一个很好的联接类型.说白了就是使用非唯一索引或非唯一索引前缀进行的查找 |
fulltext | 连接使用全文索引执行. |
ref_or_null | 这种联接类型类似于ref,但是MySQL对包含空值的行进行额外搜索.这种连接类型优化最常用于解析子查询. |
index_merge | 此联接类型指示使用索引合并优化. |
unique_subquery | 此类型替换以下形式的IN子查询的eq_ref value IN (SELECT primary_key FROM single_table WHERE some_expr) unique_subquery只是一个索引查找函数,为了更高的效率,它完全取代了子查询. |
index_subquery | 此联接类型类似于unique_subquery.它取代IN子查询,但它适用于以下形式的子查询中的非唯一索引: value IN (SELECT key_column FROM single_table WHERE some_expr) |
range | 扫描部分索引,索引范围扫描,对索引的扫描开始于某一点,返回匹配值域的行,常见于between、<、>等的查询 只检索在给定范围内的行,使用索引选择行.explain输出行中的key列指示使用了哪个索引. 键列与常量进行比较时,可以使用=, <>, >, >=, <, <=, is null, <=>, between, like,或者IN() 操作. |
index | 扫描整个索引树 索引联接类型与ALL相同,只是扫描索引树.这有两种方式:
当查询只使用作为单个索引的一部分的列时,MySQL可以使用此联接类型. |
ALL | 对先前表中的每个行组合进行全表扫描.如果该表是第一个未标记为Const的表,则这通常是不好的. |
possible_keys
possible_keys列指示MySQL可以从中选择查找该表中的行的索引.请注意,该列完全独立于EXPLAIN输出中显示的表的顺序。这意味着possible_keys中的一些键在实际生成的表顺序中可能无法使用.
如果该列为NULL,则不存在相关的索引.在这种情况下,可以通过检查WHERE子句来检查它是否引用了一些或多个适合索引的列,从而提高了查询的性能.如果是这样,请创建一个适当的索引,并再次使用EXPLAIN检查查询.
key
key列指示MySQL实际决定使用的键(索引).如果MySQL决定使用一个possible_keys可能的索引来查找行,则该索引将被列出为key值.
key可能会输出不存在于possible_keys值中的索引.如果所有possible_keys索引都不适合查找行,但查询所选择的所有列都是其他索引的列;则可能会发生这种情况.也就是说,输出的索引涵盖选定的列,因此虽然它不用于确定要检索的行,但索引扫描比数据行扫描更有效.
key_len
key_len列指示MySQL决定使用的键的长度.key_len的值使您能够确定一个多部分键,MySQL实际使用了多少个部分.如果key列为Null,则len_len列也显示Null.
由于键存储格式,可以为Null的列的键长度大于非空列的键长度.
ref
ref列显示将哪些列或常量与key列中指定的索引进行比较,以从表中选择行.
如果该值是func,则所使用的值是某个函数的结果.函数实际上可能是一个运算符,如算术运算符.
rows
rows列指示MySQL认为执行查询必须检查的行数.
对于InnoDB表,这个数字是一个估计,可能并不总是精确的.
filtered
filtered列指示将由表条件筛选后的表行的估计百分比.最大值为100,这意味着没有对行进行筛选.从100降下来的值表示过滤的数量在增加.rows显示检查的估计行数,rows×filtered显示将与接下来的表连接的行数.例如,如果行为1000,过滤后为50.00(50%),则与接下来的表连接的行数为1000×50%=500.
Extra
本专栏包含有关MySQL如何解析查询的其他信息.常见有以下几种:
- Using index:表示仅使用索引树中的信息从表中检索列信息(使用了覆盖索引),而不必进行额外的查找来读取实际行,当查询仅使用作为单个索引的一部分的列时,可以使用此策略.如果只有 Using index,说明他没有查询数据表,只用索引表就完成了这个查询.对于具有用户定义的聚集索引的InnoDB表,即使Extra列中没有Using index,也可以使用该索引.如果type是index,而key是PRIMARY,则是这种情况.
- Using where:表示条件查询,如果不读取表的所有数据,或不是仅仅通过索引就可以获取所有需要的数据,则会出现 Using where.
- Using filesort:表示没有使用索引的排序.MySQL必须执行额外的传递,以了解如何按排序顺序检索行.排序是通过根据联接类型遍历所有行并存储与WHERE子句匹配的所有行的排序键和行指针来完成的.然后对键进行排序,并按排序顺序检索行.它进行排序时使用分块排序,块内使用快速排序,如果排序内容超过默认2M大小则会创建临时文件进行分块排序.
- Using temporary:要解析查询,MySQL需要创建一个临时表来保存结果.这通常发生在查询包含以不同方式列出列的GROUPBY和ORDERBY子句时.注意这里的临时表可能是内存上的临时表,也有可能是硬盘上的临时表,理所当然基于内存的临时表的时间消耗肯定要比基于硬盘的临时表的实际消耗小.
- Using join buffer:表示使用了连接缓存.
- impossible where:where子句总是false,不能用来获取任何元组.
- select tables optimized away:在没有GROUPBY子句的情况下,基于索引优化MAX/MIN操作或者对于MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段再进行计算,在生成查询执行计划的阶段即完成优化.
- distinct:优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作.