mysql执行计划

  文章:https://blog.csdn.net/wuseyukui/article/details/71512793的学习笔记
----------------------------------------------------------------------------------------------
  目前国内大多数互联网公司使用的数据库都是mysql,虽然postgresql也很是优秀,甚至在某些方面超过mysql,但不可忽视的一个问题是mysql拥有完善的技术社区,基本上生产碰到的问题都会在社区中找到相关的处理办法。mysql毕竟不是商用数据库,在数据量偏大以后(单表几十万),基本就须要开始进行优化了。
  而sql的优化,一切都是围绕执行计划展开的,看懂mysql的执行计划也就显得尤为重要了。
  能够看到执行计划有不少字段,其中比较重要的为id、type、key、rows、extra。咱们逐个看一下各个字段的含义:
一、 id,表示语句的执行优先级,数字越大优先级越高;id相同的时候,执行顺序为从上到下;
能够看到,a,b,c三张表id都是1,表示这三个表查询的优先级都是相同的。
而上图,因为有子查询,子查询的语句优先级较高,所以id为2,比另外三个要高。除此之外,咱们还注意到,三张表的执行顺序变了,跟子查询条件关联的tb_a表变成了在id为1的状况下优先查询的表。这说明where条件能够影响表的查询顺序。
二、 select_type,查询类型;主要用于区分普通查询、联合查询、子查询等分类;
  一、 SIMPLE:简单的select查询,查询中不包含子查询或者union
  二、 PRIMARY:查询中包含任何复杂的子部分,最外层查询则被标记为primary
  三、 SUBQUERY:在select 或 where列表中包含了子查询
  四、 DERIVED:在from列表中包含的子查询被标记为derived(衍生),mysql或递归执行这些子查询,把结果放在临时表里
  五、 UNION:若第二个select出如今union以后,则被标记为union;若union包含在from子句的子查询中,外层select将被标记为derived
  六、 UNION RESULT:从union表获取结果的select
  其中一、二、3能够合起来理解,就是一个普通的查询,好比select * from table_a,咱们叫作简单查询(simple)。若是有子查询,则外层的叫主查询(primary),内层的叫子查询(subquery)。4的意思是临时表的状况,好比咱们要从一个查询的结果集中获取数据,再跟其它表进行join,则这个做为临时表跟其它表进行join操做的结果集就是派生查询(derived,派生,衍生的意思)。5跟6的意思,下图很明显了,就是union以后的查询被标记位union,最终的结果就是union result。
三、 type,访问类型;sql优化中很重要的一个指标,从好到坏一次是:
  system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
  通常来讲,好的sql查询至少达到range级别,最好能达到ref
  一、system:表里只有一行记录,至关于const类型的特例,平时几乎不会出现,能够忽略不计;
  二、const:表示经过索引一次就找到了,const用于比较primary key或者unique索引。由于只需匹配一行数据,因此很快。若是主键置于where中,mysql就能将该查询转换为一个const;const:常数;
  三、eq_ref: 惟一索引扫描,对于每一个索引键,表中只有一条记录与之匹配。常见于主键或者惟一索引。
  四、ref: 非惟一索引,返回匹配某个单独之的全部行。本质也是一种索引访问,它返回全部匹配某个单独值的行,然而它也可能会找到多个符合条件的行,因此它应该属于查找和扫描的混合体。
  五、range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了那个索引。通常就是在where中出现了between、>、<、in等的查询。这种索引列上的范围扫描比全索引扫描要好。只须要开始于某个点,结束语某个点,不用扫描所有索引。
  六、index:全索引扫描;index与all区别是index类型只遍历索引树,而all为全表扫描;二者虽然都是全表扫描,但index是从索引中读取,而all是从硬盘读取;
  id为主键,有主键索引,但由于要查找全部的id,所以须要扫描所有索引,上图走的是age_index索引,不是主键索引,由于此时主键没有索引,若在主键添加惟一索引id_index,则key列会变为id_index,表示使用的是主键的惟一索引;name字段没有索引,故而扫描全表数据:
四、 possible_keys:查询涉及到的字段上存在索引,则列出该索引,但不必定会被使用;
五、 key:真正使用的索引;
六、 key_len:表示索引中使用的字节数,能够经过该列计算查询中使用的索引的长度;并不是实际使用长度,即key_len是根据表定义计算而得,不是经过表内检索出的。理论上越小越好。
七、 ref:当前表在利用key列记录中的索引进行查询时,用到的列或者常数。
八、 rows:查询所涉及的表数据的行数,越小越好;
九、 extra:扩展信息,不适合在其余字段中展现,但十分重要的额外信息;
  一、using filesort:mysql对数据使用一个外部的索引排序,而不是按照表内的索引进行排序读取。也就是mysql没法利用索引完成的排序操做称为“文件排序”;
  因为name字段没有索引,咱们在利用主键完成数据检索后按name进行排序,这个时候mysql是不知道如何进行的,由于name没有现成的索引排序,所以mysql内部必须再实现一次“文件排序”;
  二、using temporary:使用临时表保存中间结果,也就是mysql在对查询结果进行排序时使用了临时表,常见于order by跟group by
  三、using index:表示相应的select操做中使用了覆盖索引,避免了访问表的数据行,效率高;
若是同时出现了using where,代表索引被用来执行索引键值的查找;若是没有同时出现using where,代表索引用来读取数据,而非进行查找动做;
  覆盖索引:
  实际上就是数据存在了索引上,所以在查询的时候,只须要读取了索引也就顺便拿到了数据,不须要再次经过索引中的指针去查找硬盘中的表数据。固然,这种状况下,由于索引中包含数据,故而索引一般体积是比较大的,因此,通常来讲,对于一张表,只有一个覆盖索引,这个索引一般都是主键索引。想一下,若是一个表有两个覆盖索引,那这个表的数据不是有2份了么,这太浪费存储空间了。
  四、using where:使用了where过滤条件;
  五、using join buffer:使用了链接缓存;
  六、impossible where:where子句中的值老是false,不能用来过滤任何数据;
  七、select tables optimized away:在没有group by子句的状况下,基于索引优化min/max操做或者对于myisam引擎优化count(*)操做,没必要等到执行阶段再进行计算,查询执行计划生成的阶段便可完成优化;
  八、distinct:优化distinct操做,在找到第一个匹配的数据后即中止查找一样值的操做;
相关文章
相关标签/搜索