首页 > 技术文章 > 执行计划mysql

luyShare 2020-12-28 20:28 原文

 

模拟优化器执行SQL查询语句,从而知道数据库如何处理SQL,分析查询语句或表结构的性能瓶颈。

 


 

mysql---explain

explain + sql

执行结果字段解释:

 ID

 

 

 

      相同,执行顺序由上至下

  

 

 

    执行顺序是t1,t3,t2,select_type提示都是简单查询

------------------------------------------------------------------------------------------------

  如果是嵌套子查询,id会递增,id越大越先执行

 

 

 这个很好理解,括号里的子查询先被执行,select_type字段也标识出来哪些是子查询。

---------------------------------------------------------------------------------------

  既有相同又有不同,id越大越先执行,相同的顺序执行

  

 

 

 这里S1是衍生表,所以table部分是derived2,derived是衍生的意思,2指的是由哪个ID衍生出来。

-----------------------------------------------------------------------------------------------

select_type

查询类型

  simple:简单查询,不包括子查询,union等;

  primary:查询中若包含任何复杂的子查询,最外层被标记为这个类型,就是最后被加载的那个,但是多表查询时可能有多个primary;

  subquery:子查询部分;

  derived:在from列表中包含的子查询被标记为derived(衍生);

  union:若第二个select出现在union之后,则被标记为union,

       若union包含在from子句的子查询中,则外层select将被标记为derived;

  union result:union后的结果集。

 

table

数据来自哪张表

 

type

访问类型排序,从好到差依次是

  system>const>eq_ref>ref>range>index>All

  system:表只有一条记录,这是const类型的特例,平时不会出现,可以忽略不计;

  const:表示通过索引一次就找到了,用于比较主键或唯一索引,因为只匹配一行数据,所以很快,如果将主键置于where条件中,就会是const类型;

  eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配;

  ref:非唯一性索引扫描,对于每个索引键,表中有多条记录与之匹配,假设部门id是索引,查这个部门id对应的员工,有多条数据;

  range:通过一个索引来检索一个范围内的记录,假设订单创建时间是索引,查询最近一个月内的订单,例如>,<,between,in;

  index:查询的结果就是索引的值,及遍历的是索引树而不是表,例如查询表的所有主键;

  All:遍历全表,但是ALL也不代表一定要优化,假如某个表数据量少,字段也少,我就需要全查出来,分页都不用,那就完全不需要优化。

  

possible_keys

  显示可能应用在这个表中的索引,一个或多个,但不一定被查询使用。

key

  实际使用的索引;

  查询中若使用了覆盖索引,则该索引仅出现在key列表中。

  覆盖索引:指的是要查询的内容,都在索引上,刚好被索引覆盖,也就是只需要查询索引,不需要查询表了,通常就是联合索引比较容易实现覆盖索引。

 

 key_len

  表示索引中使用的字节数,说白了就是查询条件里索引用的越多,len越长,但是这一点需要和查询结果的精度同时考虑,取平衡。

 

ref

  type 是 ref 时,显示索引的哪一列被使用了,如果可能的话,是一个常数。

 

row

  查询到符合条件的结果为止,每张表有多少数据被查询过。

 

extra

  不适合显示在以上字段里的重要内容

  比较重要的信息有

  Using filesort :说明会对数据使用一个外部的索引排序,而不是按照表设计的索引,即“文件排序”,这个要尽量避免,通常来说就是你的排序字段不在索引中;

         另外还有一种情况,一个复合索引a1_a2_a3,通过a1作为条件查询出a1,a3,然后按a3排序,这种情况虽然a1,a3都在复合索引a1_a2_a3中,但是没有a2,所以出现文件排序,解决方案就是,将a2加入到排序/查询结果中去,这样虽然看上去sql复杂了一些,但其实性能更好;

  Using temporary:使用了临时表保存中间结果,指数据库自己创建了临时表用于排序/分组,使用完后删除,常见于排序order by和分组group by,这个要绝对避免。

          举个例子,有复合索引a1_a2_a3,然后查询语句分组group by a2,这时就会出现这个提示,因为数据库需要对a1的分组情况做临时表,所以这种情况下,直接group by a1,a2性能更好,说白了就是,如果要分组,分组条件最好是索引。

          需要注意的是,group by a1/a1,a2/a1,a2,a3都可以,但是group bu a1,a3/a2,a3不行,依然会报这个问题,因为复合索引内的字段是有顺序的,不能跳过。

  Using Index:表示使用了覆盖索引,避免了查询表,效率很好;

  Using Where:表面where条件里用了索引;

  

  

 

推荐阅读