MySQL - explain 执行计划详解

explain显示了MySQL如何使用索引来处理select语句以及连接表,可以帮助选择更好的索引和写出更优化的查询语句。

explain 查询结果如下

字段说明:

列名 说明
id

id列的编号是select的序列号,有几个select就有几个id,并且id是按照select出现的顺序增长的,id列的值越大优先级越高,id相同则是按照执行计划列从上往下执行,id为空则是最后执行。

select_type

表示对应行是简单查询还是复杂查询,可以为以下任何一种:

  • SIMPLE不包含子查询和union的简单查询
  • PRIMARY最外面的 SELECT
  • UNIONUNION操作中,查询中处于内层的SELECT(内层的SELECT语句与外层的SELECT语句没有依赖关系)
  • DEPENDENT UNIONUNION操作中,查询中处于内层的SELECT(内层的SELECT语句与外层的SELECT语句有依赖关系)
  • UNION RESULTUNION 的合并的结果
  • SUBQUERY子查询中首个SELECT(如果有多个子查询存在)
  • DEPENDENT SUBQUERY子查询中首个SELECT,但依赖于外层的表(如果有多个子查询存在),该类型会严重消耗性能,不会进行子查询,会先进行外部查询,生成结果集,再在内部进行关联查询,子查询的执行效率受制于外层查询的记录数,可以尝试改成join查询。
  • DERIVED包含在from子句中的子查询。mysql会将查询结果放入一个临时表中,此临时表也叫衍生表。
table 输出的行所引用的表
partitions 如果查询是基于分区表的话,显示查询将访问的分区。
type

联接类型。下面给出各种联接类型,按照从最佳类型到最坏类型进行排序:

  • system表仅有一行 (= 系统表)。这是 const 联接类型的一个特例。
  • const表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const 表很快,因为它们只读取一次!
  • eq_ref主键或唯一键索引被连接使用,最多只会返回一条符合条件的记录。简单的select查询不会出现这种type。这可能是最好的联接类型,除了 const 类型。
  • ref相比eq_ref,不使用唯一索引,而是使用普通索引或者唯一索引的部分前缀,索引和某个值比较,会找到多个符合条件的行。
  • ref_or_null该联接类型如同 ref, 但是添加了 MySQL 可以专门搜索包含 NULL 值的行。
  • index_merge该联接类型表示使用了索引合并优化方法。
  • unique_subquery该类型替换了下面形式的 IN 子查询的 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通常出现在范围查询中,比如in、between、大于、小于等。使用索引来检索给定范围的行。
  • index扫描全索引拿到结果,一般是扫描某个二级索引,二级索引一般比较少,所以通常比ALL快一点,因为索引文件通常比数据文件小。
  • ALL对于每个来自于先前的表的行组合,进行全表扫描,说明查询就需要优化了。

一般来说,得保证查询至少达到 range 级别,最好能达到 ref。

possible_keys 此列显示在查询中可能用到的索引。如果该列为NULL,则表示没有相关索引,可以通过检查where子句看是否可以添加一个适当的索引来提高性能。
key 此列显示MySQL在查询时实际用到的索引。在执行计划中可能出现possible_keys列有值,而key列为null,这种情况可能是表中数据不多,MySQL认为索引对当前查询帮助不大而选择了全表查询。如果想强制MySQL使用或忽视possible_keys列中的索引,在查询时可使用force index、ignore index。
key_len

此列显示MySQL在索引里使用的字节数,通过此列可以算出具体使用了索引中的那些列。索引最大长度为768字节,当长度过大时,MySQL会做一个类似最左前缀处理,将前半部分字符提取出做索引。当字段可以为null时,还需要1个字节去记录。在不损失精确性的情况下,长度越短越好。

  • char(n):n个数字或者字母占n个字节,汉字占3n个字节
  • varchar(n):n个数字或者字母占n个字节,汉字占3n+2个字节。+2字节用来存储字符串长度。
  • tinyint:1字节
  • smallint:2字节
  • int:4字节
  • bigint:8字节
  • date:3字节
  • timestamp:4字节
  • datetime:8字节
ref 此列显示key列记录的索引中,表查找值时使用到的列或常量。常见的有const、字段名
rows

此列是MySQL在查询中估计要读取的行数。注意这里不是结果集的行数。

filtered 显示了通过条件过滤出的行数的百分比估计值。
Extra

该列包含 MySQL 解决查询的详细信息

  • DistinctMySQL 发现第 1 个匹配行后,停止为当前的行组合搜索更多的行。
  • Select tables optimized away使用某些聚合函数(比如 max、min)来访问存在索引的某个字段,MySQL 根本没有遍历表或索引就返回数据了,表示已经优化到不能再优化了
  • Not existsMySQL 能够对查询进行 LEFT JOIN 优化,发现 1 个匹配 LEFT JOIN 标准的行后,不再为前面的的行组合在该表内检查更多的行。
  • range checked for each record (index map: #)MySQL 没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。
  • Using filesort将使用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序,说明查询就需要优化了。
  • Using index从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。
  • Using index condition:查询的列不完全被索引覆盖,where条件中是一个查询的范围。
  • Using temporaryMySQL需要创建一张临时表来处理查询,说明查询就需要优化了。
  • Using where使用 where 语句来处理结果,并且查询的列未被索引覆盖。
  • Using sort_union(...), Using union(...), Using intersect(...)这些函数说明如何为 index_merge 联接类型合并索引扫描。
  • Using index for group-by类似于访问表的 Using index 方式,Using index for group-by 表示 MySQL 发现了一个索引,可以用来查 询 GROUP BY 或 DISTINCT 查询的所有列,而不要额外搜索硬盘访问实际的表。

猜你喜欢

转载自blog.csdn.net/weixin_44988085/article/details/128632627