Mysql 性能分析之Explain

Explain 是什么?

简称执行计划,使用explain关键字可以模拟优化器执行sql查询语句,从而知道Mysql是如何处理你的sql语句的,分析你的查询语句或是表结构性能瓶颈

举个例子

explain select * from nsi_post_category_item ci
where exists (select 1 from nsi_post_category pc where ci.parent_id = pc.id )
and is_check = 1

explain分析

id(查询序列号)

选择标识符,select查询序列号
id相同时,执行顺序相同,id值越大优先级越高,越先被执行

select_type(查询类型)

展示查询中每个select子句的类型

  • SIMPLE 简单select,不使用union或子查询等
  • PRIMARY 子查询中最外层查询,查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY
  • UNION 若第二个select出现在union之后,则被标记为UNION
  • SUBQUERY 在select中或where中使用了子查询
  • DERIVED 若第二个select出现在union之后,则被标记为UNION,若union包含在FROM子句的子查询中,外层select被标记为(衍生)
  • UNION RESULT 从union表获取结果的select

table(表)

显示这一步所访问数据库中表名称,有时不是真实的表名字,可能是简称,例如上面的ci,pc,也可能是第几步执行的结果的简称

type(访问类型)

对数据库表的访问方式,标识Mysql在表中找到所需行的方式(从左至右,性能从好到坏)

system > const > eq_ref > ref > range > index > All 
  • ALL Full Table Scan 遍历全表找到匹配的行
  • index Full Index Scan index与All区别在于index类型只遍历所引树,通常比All快,因为索引文件通常比数据文件小(也就是说虽然all和index都是读全表)但index时从索引中读取的,而all时从硬盘中读的
  • range 只检索给定的范围的行,使用一个索引来选择行,key列显示使用了哪个索引,一般就是在你的where语句中出现了between / in等查询,这种范围扫描比全表扫描更好,因为它们只需要开始于索引的某一点,结束于另一点,不用扫描全部索引
  • ref 非唯一性索引扫描,返回匹配某个单独值得所有行,本质上也是一种索引访问,它返回所有匹配某个单独值得行,然而,它可能会找到更多符合条件的行,所以他应该属于查找和扫描的混合体
  • eq_ref 唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描
  • const 通过一次索引直接找到,const比较于主键或唯一索引,因为只匹配一行数据,所以很快将主键置于where列表中,Mysql就能将该查询转换为一个常量
  • system 表中有一行记录(类似系统表),平时不会出现,也可以忽略不计

possible_keys(是否存在键)

MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定
会使用到(该查询可以利用的索引,如果没有任何索引显示 null)

key(使用到的键)

显示MySQL实际决定使用的键(索引),必然包含在possible_keys中

key_len(键的字节长度)

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度,不损失精确性的情况下,长度越短越好

ref

列与索引的比较,表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

rows(行数)

估算出结果集行数,表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数

Extra(详细信息)

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

  • Using filesort(优化) 说明Mysql对数据使用一个外部的索引排序,而不是按照索引顺序进行排序,Mysql无法利用索引完成的排序操作成为文件排序
  • Using temporary(必须优化) 使用了临时表保存中间结果,Mysql在对查询结果排序时使用了临时表,常见于order by和分组查询group by
  • Using index(恭喜) 表明该次查询使用了覆盖索引,避免访问了表的数据行,效率很好,如果同时出现using where,表明索引被用来执行索引键值的查找,如果没有出现using where,表明索引用来读取数据而非执行查找的动作

覆盖索引(Convering Index)
select的数据列从索引中就能读取,不必读取数据行,Mysql可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件(省略了回表)

  • Using where 使用了where过滤条件
  • Using join buffer 使用了连接缓存
  • impossible where where子句的值总是false,不能用来获取任何元素,例如:
select * from emp where name = 'Zhangsan' and name = 'LiSi';
  • select tables optimized away 没有Group by情况下,基于索引优化Min/Max操作
  • distinct 优化distinct,找到第一匹配元组后既停止找到同样的动作
发布了9 篇原创文章 · 获赞 9 · 访问量 613

猜你喜欢

转载自blog.csdn.net/weixin_41241629/article/details/103906143