Mysql 性能优化Explain详解
explain
功能
我们在日常使用中,使用慢查询找到执行时间比较久的查询,然后使用SHOW STATUS、SHOW PROFILE、和explain做单条语句的分析。
使用explain关键字可以模拟优化器执行sql查询语句,从而知道Mysql是如何处理你的sql语句的。分析你的查询语句或者表结构的性能瓶颈。
具体可以分析哪些
- 表的读取顺序
- 数据读取操作的操作类型
- 哪些索引可以使用
- 哪些索引被实际使用
- 表之间的引用
- 每张表有多少行被优化器查询
使用语法
explain sql语句
得到了什么结果
expain出来的信息有10列,分别是id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
字段概要解释:
- id:选择标识符
- select_type:表示查询的类型。
- table:输出结果集的表
- partitions:匹配的分区
- type:表示表的连接类型
- possible_keys:表示查询时,可能使用的索引
- key:表示实际使用的索引
- key_len:索引字段的长度
- ref:列与索引的比较
- rows:扫描出的行数(估算的行数)
- filtered:按表条件过滤的行百分比
- Extra:执行情况的描述和说明
字段详细解释
一、 id
SQL执行查询的顺序的标识
1. id相同时,执行顺序由上至下
2. id不同时,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
3. id相同和不同同时存在,id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行
二、select_type
查询中每个select子句的类型,主要用于区别普通查询、联合查询、子查询等复杂查询
(1) SIMPLE(简单SELECT,不使用UNION或子查询等)
(2) PRIMARY(子查询中最外层查询,查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY)
(3) UNION(UNION中的第二个或后面的SELECT语句)
(4) DEPENDENT UNION(UNION中的第二个或后面的SELECT语句,取决于外面的查询)
(5) UNION RESULT(UNION的结果,union语句中第二个select开始后面所有select)
(6) SUBQUERY(子查询中的第一个SELECT,结果不依赖于外部查询)
(7) DEPENDENT SUBQUERY(子查询中的第一个SELECT,依赖于外部查询)
(8) DERIVED(派生表的SELECT, FROM子句的子查询)
(9) UNCACHEABLE SUBQUERY(一个子查询的结果不能被缓存,必须重新评估外链接的第一行)
三、table
显示这一步所访问数据库中表名称(显示这一行的数据是关于哪张表的)
四、type
表示MySQL在表中找到所需行的方式,又称“访问类型”,常见类型如下:
ALL, index, range, ref, eq_ref, const, system, NULL
从左到右,性能从最差到最好
一般来说。得保证查询至少达到range级别,最好能达到ref。
所有的访问类型排序:
system:表只有一行记录(等于系统表),这是const类型的特别,平时不会出现,这个可以忽略不计。
const:表示通过索引一次就找到了,const用于比较primary key或者unique索引,因为只匹配一行数据,所以很快
如将主键置于where列表中,Mysql就能将该查询转换为一个常量
eq_ref:唯一性索引扫描,对于每个索引键,表只只有一条记录与之匹配。常见于主键或唯一索引扫描
ref:非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问,它返回匹配某个单独值的行,然而,它可能会找到多个符合条件的行,索引他应该属于查找和扫描的混合体
range:只检索给定范围的行,使用一个索引来选择行。
key列显示使用了哪个索引,一般就是在你的where语句中出现了between、<、>、in等的查询
这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,面结束另一点,不用扫描全部索引。
index: Full Index Scan,index与ALL区别为index类型只遍历索引树,这通常比ALL快,因为索引文件通常比数据文件小,
也就是说虽然ALL和Index都是读全表,但Index是从索引中读取的,而ALL都是从磁盘中读的。
ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行。NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。
五、possible_keys
显示可能应用在这张表中的索引,一个或多个。
查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。
简单来说,mysql认为这条查询可能用到哪些索引。
六、Key
key列显示MySQL实际决定使用的键(索引),必然包含在possible_keys中
如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。
七、key_len
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)
同样的查询结果夏,不损失精确性的情况下,长度越短越好 。
八、ref
显示索引的哪一列被使用了,如果可能的话,是一个常数,哪些列或者常量被用于查询索引列上的值。
九、rows
估算出结果集行数,表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数
十、Extra
该字段包含MySQL解决查询的详细信息,有以下几种情况:
Using filesort:
说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。
Mysql中无法利用索引完成的排序操作称为“文件排序”,如果出现,要优化此查询。
简单来说:Mysql并未按照你建立的索引去查找,
Using temporary:
使用了临时表中保存中间结果,Mysql在对查询结果排序时使用临时表。常见于排序order by和分组查询group by。
Using index:
表示相应的select操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错。
如果同时出现using where,表明索引被用于来执行索引键值的查找。
如果没有同时出现wing where,表明索引用来读取数据而非执行查找动作。
Using where :
表明使用了where过滤
Using join buffer:
使用了连接缓存
impossible where:
where子句中的值总是false,不能用来获取任何元组