mysql中explain的用法和解释

时间:2023-01-31 18:15:03

对于mysql查询性能分析时经常使用explain关键字对查询语句进行分析,就explain相关字段进行记录。

explain的每个输出行提供一个表达额相关信息,每个行包括下面的列

  1. id
  2. select_type
  3. table
  4. type
  5. possible_keys
  6. key
  7. key_len
  8. ref
  9. rows
  10. extra
    mysql中explain的用法和解释

(这里仅仅是为了显示各个字段)

下面就各字段含义进行介绍

id

本次查询的标识符,在查询中的每个select都有一个顺序的数值

select_type

select 的类型,可能有以下几种:

  • simple 简单的select,没有使用union或子查询
  • primary 最层的select
  • union 第二层,在select后使用了union
  • dependent union 子查询的第一个select,依赖于外部子查询
  • subquery 子查询的第一个select
  • dependent subquery 子查询的第一个subquery,依赖于外部的子查询
  • derived 派生表select(from 子句中的子查询)

table

记录查询引用的表

type

表连接类型,以下是各种不同连接类型(从好到坏)
一般来说,得保证查询至少达到range级别,最好能达到ref。

  • system:表只有一行数据(相当于系统表),这是const表连接类型的一个特例
  • const:表中最多只有一行匹配记录,在查询一开始就会被读取出来。由于只有一行记录,在余下的优化程序里该行记录的字段值可以被当作是一个恒定值。const表查询起来非常快,因为只要读取一次!const 用于在和 primary key 或unique 索引中有固定值比较的情形。

  • eq_ref:对于每个来自于前面的表的行组合,从该表中读取一行。除了const类型,这是最好的连接类型。它用在索引所有部分都用于做连接并且这个索引是一个primary key 或 unique 类型。eq_ref可以用于在进行”=”做比较时检索字段。比较的值可以是固定值或者是表达式,表达示中可以使用表里的字段,它们在读表之前已经准备好了。

  • ref:对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。 ref还可以用于检索字段使用 =操作符来比较的时候。

  • ref_or_null:这种连接类型类似 ref,不同的是mysql会在检索的时候额外的搜索包含null 值的记录。这种连接类型的优化是从mysql4.1.1开始的,它经常用于子查询。

  • index_merge 该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。

  • unique_subquery:这种类型用例如一下形式的 in 子查询来替换 ref:
    value in (select primary_key from single_table where some_expr),只是用来完全替换子查询的索引查找函数效率更高了。

  • index_subquery:这种连接类型类似 unique_subquery。它用子查询来代替in,不过它用于在子查询中没有唯一索引的情况下。

-range:在给定范围的记录中,利用索引来取得一条数据。key字段表示使用了哪个索引。key_len字段包括了使用的键的最长部分。这种类型时 ref 字段值是 null。range用于将某个字段和一个定植用以下任何操作符比较时 =, <>, >,>=, <, <=, is null, <=>, between, 或 in:
select * from tbl_name where key_column = 10; select * fromtbl_name where key_column between 10 and 20; select * from tbl_namewhere key_column in (10,20,30); select * from tbl_name wherekey_part1= 10 and key_part2 in (10,20,30);

  • index:连接类型跟 all 一样,不同的是它只扫描索引树。它通常会比 all快点,因为索引文件通常比数据文件小。mysql在查询的字段知识单独的索引的一部分的情况下使用这种连接类型。

  • all:将对该表做全部扫描以和从前一个表中取得的记录作联合。这时候如果第一个表没有被标识为const的话就不大好了,在其他情况下通常是非常糟糕的。正常地,可以通过增加索引使得能从表中更快的取得记录以避免all。

possible_keys

possible_keys字段是指 mysql在搜索表记录时可能使用哪个索引。注意,这个字段完全独立于explain 显示的表顺序。这就意味着 possible_keys里面所包含的索引可能在实际的使用中没用到。如果这个字段的值是null,就表示没有索引被用到。这种情况下,就可以检查 where子句中哪些字段那些字段适合增加索引以提高查询的性能。就这样,创建一下索引,然后再用explain 检查一下。

key

key字段显示了mysql实际上要用的索引。当没有任何索引被用到的时候,这个字段的值就是null。想要让mysql强行使用或者忽略在 possible_keys字段中的索引列表,可以在查询语句中使用关键字force index, use index,或 ignore index。如果是 myisam 和 bdb 类型表,可以使用 analyzetable 来帮助分析使用使用哪个索引更好。如果是 myisam类型表,运行命令 myisamchk –analyze也是一样的效果。

key_len

key_len 字段显示了mysql使用索引的长度。当 key 字段的值为 null时,索引的长度就是 null。注意,key_len的值可以告诉你在联合索引中mysql会真正使用了哪些索引。

ref

ref 字段显示了哪些字段或者常量被用来和 key配合从表中查询记录出来。

rows

rows 字段显示了mysql认为在查询中应该检索的记录数。

extra

  • distinct
    mysql当找到当前记录的匹配联合结果的第一条记录之后,就不再搜索其他记录了。
  • not exists
    mysql在查询时做一个 left join优化时,当它在当前表中找到了和前一条记录符合 left join条件后,就不再搜索更多的记录了。下面是一个这种类型的查询例子:
    select * from t1 left join t2 on t1.id=t2.id where t2.id isnull;
    假使 t2.id 定义为 not null。这种情况下,mysql将会扫描表 t1并且用 t1.id 的值在 t2 中查找记录。当在 t2中找到一条匹配的记录时,这就意味着 t2.id 肯定不会都是null,就不会再在 t2 中查找相同 id值的其他记录了。也可以这么说,对于 t1 中的每个记录,mysql只需要在t2 中做一次查找,而不管在 t2 中实际有多少匹配的记录。
  • range checked for each record
    mysql没找到合适的可用的索引。取代的办法是,对于前一个表的每一个行连接,它会做一个检验以决定该使用哪个索引(如果有的话),并且使用这个索引来从表里取得记录。这个过程不会很快,但总比没有任何索引时做表连接来得快。
  • using filesort:
    mysql需要额外的做一遍从而以排好的顺序取得记录。排序程序根据连接的类型遍历所有的记录,并且将所有符合 where条件的记录的要排序的键和指向记录的指针存储起来。这些键已经排完序了,对应的记录也会按照排好的顺序取出来。
  • using index
    字段的信息直接从索引树中的信息取得,而不再去扫描实际的记录。这种策略用于查询时的字段是一个独立索引的一部分。
  • using temporary
    mysql需要创建临时表存储结果以完成查询。这种情况通常发生在查询时包含了groupby 和 order by 子句,它以不同的方式列出了各个字段。
  • using where
    where子句将用来限制哪些记录匹配了下一个表或者发送给客户端。除非你特别地想要取得或者检查表种的所有记录,否则的话当查询的extra 字段值不是 using where 并且表连接类型是 all 或 index时可能表示有问题。