MySQL优化(4):explain分析

Explain是Mysql的自带查询优化器,负责select语句的优化器模块,可以模拟优化器执行SQL查询语句,从而知道Mysql是如何处理SQL的,语法也很简单:Explain + SQL

以下是通过explain查询出的几个属性

   

(常见性能瓶颈 ——

 CPU:CPU饱和一般发生在数据装入内存或从磁盘上读取数据时

 IO:磁盘I/O瓶颈发生在装入数据远大于内存容量时

 服务器硬件的性能瓶颈:top,free,iostat,vmstat来查看系统的性能状态)

 

用途:

(1)表的读取顺序,id

(2)数据读取操作的操作类型,select_type

(3)哪些索引可以使用

(4)哪些索引被实际使用

(5)表之间的引用

(6)每张表有多少行被优化器查询 rows

1、id:反映的是表的读取的顺序,或查询中执行select子句的顺序。

小表永远驱动大表,三种情况:

(1)id相同,执行顺序是由上至下的

(2)id不同,如果是子查询,id序号会递增,id值越大优先级越高,越先被执行

(3)id存在相同的,也存在不同的,所有组中,id越大越先执行,如果id相同的,从上往下顺序执行

  

  derived是衍生虚表的意思,derived2中的2对应id2

2、select_type:反映的是Mysql理解的查询类型

(1)simple:简单的select查询,查询中不包含子查询或union。

(2)primary:查询中若包含任何复杂的字部分,最外层查询标记为primary。

(3)subquery:select或where列表中的子查询。

(4)derived(衍生):在from列表中包含的子查询,Mysql会递归执行这些子查询,把结果放在临时表里。

(5)union:若第二个select出现在union后,则被标记为union,若union包含在from字句的子查询中,外层select将被标记为derived

(6)union result:union后的结果集

3、table:反映这一行数据是关于哪张表的

4、type:访问类型排序

反映sql优化的状态,至少达到range级别,最好能达到ref

查询效率:system > const > eq_ref > ref > range > index > all

  (完整的排序:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index >all)  

(1)system:从单表只查出一行记录(等于系统表),这是const类型的特例,一般不会出现

(2)const:查询条件用到了常量,通过索引一次就找到,常在使用primary key或unique索引中出现。

   

  where id=1写死,所以类型是const

(3)eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描。

(4)ref:非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问,它可能会找到多个符合条件的行,与eq_ref的差别是eq_ref只匹配了一条记录。

(5)range:只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引,一般是在where语句中出现了between、<、>、in等的查询。

   这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一点,不用扫描全部索引。与eq_ref和ref的区别在于筛选条件不是固定值,是范围。

  

(6)index:full Index scan,index和all的区别为index类型只遍历索引树。这通常比all快,因为索引文件通常比数据文件小。

  

  要获得的id信息,刚好id在索引上,从索引中读取

   (all和index都是读全表,但index是从索引中读取的,而all是从硬盘中读的)

(7)all:全表扫描,如果查询数据量很大时,全表扫描效率是很低的。

5、possible_keys、key、key_len:反映实际用到了哪个索引,索引是否失效

(1)possible_keys:Mysql推测可能用到的索引有哪些,但不一定被查询实际使用

(2)key:实际使用的索引,若为null,则可能没建索引或索引失效。

     

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

  覆盖索引:select后面的字段和所建索引的个数、顺序一致)

(3)key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。同样的查询结果下,长度越短越好。

    key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的。

6、ref:反映哪些列或常量被用于查找索引列上的值

   

7、rows:根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数

  

  仅通过主键索引查找是641行

   

  建完相关的复合索引再查,需要查询的行数就变少了

8、Extra

(1)using filesort:mysql中无法利用索引完成的排序,这时会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。

    

  创建索引时就会对数据先进行排序,出现using filesort一般是因为order by后的条件导致索引失效,最好进行优化。

   

  order by的排序最好和所建索引的顺序和个数一致

(2)using temporary:使用了临时表保存中间结果,mysql在对查询结果排序时使用临时表。常见于排序order by和分组查询group by。

   

  影响更大,所以要么不建索引,要么group by的顺序要和索引一致

   

(3)using index:表示相应的select操作中使用了覆盖索引,避免访问了表的数据行,效率好

  覆盖索引:select后的数据列只从索引就能取得,不必读取数据行,且与所建索引的个数(查询列小于等于索引个数)、顺序一致。

  所以如果要用覆盖索引,就要注意select的列只取需要用到的列,不用select *,同时如果将所有字段一起做索引会导致索引文件过大,性能会下降。

  

  出现using where,表明索引被用来执行索引键值的查找

   

  如果没有同时出现using where,表明索引用来读取数据而非执行查找动作。

(4)using where:表明使用了where过滤

(5)using join buffer:使用了连接缓存

(6)impossible where:where子句的值是false

(7)select tables optimized away

(8)distinct:优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作

posted @ 2018-06-09 19:24  湮天霸神666  阅读(4958)  评论(0编辑  收藏  举报