MySQL 5.6.3以前只能EXPLAIN SELECT; 5.6.3当前就能够EXPLAIN SELECT,UPDATE,DELETE


有这样一张user表,300多万行记录,表构造及索引信息如下:



对于sql:

SELECT    * FROM    `user` WHERE    id > 20000     AND country > 1     AND grade IN ( 1, 4 )     AND city IN ( 1, 500, 1000, 1500, 3000 ) ORDER BY    update_time DESC     LIMIT 30;

explain后果如下:







<font color="#4682B4"> 1.id </font>


SQL查问中的序列号

id列数字越大越先执行,如果说数字一样大,那么就从上往下顺次执行。



<font color="#4682B4"> 2.select_type </font>


查问的类型, 能够是如下的任何一种类型:



<font color="#4682B4">3.table </font>


查问的表名. 并不一定是理论存在的表名.

能够为如下的值:

  • <unionM,N>: 援用id为M和N UNION后的后果。
  • <derivedN>: 援用id为N的后果派生出的表。派生表能够是一个后果集,例如派生自FROM中子查问的后果。
  • <subqueryN>: 援用id为N的子查问后果物化失去的表。即生成一个长期表保留子查问的后果。


<font color="#4682B4"> 4.partitions</font>


5.7以前,该项是explain partitions显示的选项; 5.7当前成为了默认选项.

该列显示的为分区表命中的分区状况, 非分区表该字段为空(NULL).



<font color="#FFD700"> 5.type</font>


最重要的一个指标, 显示查问应用了何种类型

ALL之外, 其余type都能够用到索引; 除index_merge外, 其余type只可用到一个索引.


由左到右,性能由差到好:

ALL,index,range,index_subquery,unique_subquery,index_merge,ref_or_null,fulltext,ref,eq_ref,const,system

从上到下,性能由差到好:


<font color="#FF7F50">(1) ALL</font>


扫描全表,性能最差.

>>>>>>


<font color="#FF7F50">(2) index</font>


扫描全副索引树

或称"索引全表扫描", 即把索引从头到尾扫一遍.

蕴含两种状况:

  1. 查问应用了笼罩索引, 那么只须要扫描索引就能够取得数据. 这个效率要比全表扫描快, 因为索引通常比数据表小, 且还能防止二次查问. 这种状况在extra中显示Using index.
  2. 反之, 如果在索引上进行全表扫描,则extra字段没有Using index.


如对于user表,telephone字段建有索引,如果

<1>.

explain select telephone from user;,则type字段将为index


<2>.

explain select amount_coin from user;,

因为amount_coin字段没有建索引, 故而type字段将为ALL


<3>.

explain select * from user;,

如果蕴含没有建索引的列, type字段也将为ALL

>>>>>>


<font color="#FF7F50">(3) range</font>


扫描局部索引

索引范畴扫描, 对索引的扫描开始于某一点, 返回匹配值域的行,常见于 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN()或者like等运算符的查问中

>>>>>>


<font color="#FF7F50">(4) index_subquery</font>


该联接类型相似于上面的unique_subquery

实用于非惟一索引, 能够返回反复值.

>>>>>>


<font color="#FF7F50">(5) unique_subquery</font>


用于wherein模式的子查问.

子查问返回不反复值惟一值, 能够齐全替换子查问, 效率更高.

该类型替换了上面模式的IN子查问的ref:

value IN (SELECT primary_key FROM single_table WHERE some_expr)

>>>>>>


<font color="#FF7F50">(6) index_merge</font>


示意查问应用了两个以上的索引, 最初取交加或者并集, 常见and ,or的条件应用了不同的索引.

官网排序这个在上面的ref_or_null之后, 但实际上因为要读取多个索引,性能可能大部分工夫都不如更上面的range

>>>>>>


<font color="#FF7F50">(7) ref_or_null</font>


跟上面的ref类型相似, 只是减少了null值的比拟.

理论用的不多

>>>>>>


<font color="#FF7F50">(8) fulltext</font>


应用全文索引type会是这个类型.

留神,全文索引的优先级很高,若全文索引一般索引同时存在时, mysql不论代价, 会优先选择应用全文索引

>>>>>>


<font color="#FF7F50">(9) ref</font>


应用非惟一索引或非惟一索引前缀进行的查找

对于来自前表的每一行,在以后表的索引中能够匹配到多行.

若连贯只用到索引的最左前缀索引不是主键或惟一索引时, 应用ref类型(能够了解成可能呈现"一对多"时)

ref可用于应用'='或'<=>'操作符作比拟的索引列

>>>>>>


<font color="#FF7F50">(10) eq_ref</font>


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


eq_refconst的区别:

eq_ref 呈现于多表join时, 对于来自前表的每一行, 在以后表中只能找到一行.

这是除了上面几种类型之外最好的类型. 当主键或惟一非NULL索引的所有字段都被用作join联接时会应用此类型.

eq_ref 可用于应用'='操作符作比拟的索引列, 比拟的值能够是常量, 也能够是应用在此表之前读取的表的列的表达式.

>>>>>>


<font color="#FF7F50">(11) const</font>


const: 单表中最多有一个匹配行, 例如依据主键或惟一索引查问.
(如 select * from user where id=100),
查问起来十分迅速

>>>>>>


<font color="#FF7F50">(12) system</font>


systemconst类型的特例,只会呈现在MyisamMemory存储引擎, 当查问的表只有一行或空表的状况下,type字段将是system.

如果是Innodb引擎表, type列在这种状况通常都是ALL或者index.

这种类型能够能够忽略不计

>>>>>>


<font color="#FF7F50">(13) NULL</font>


不必拜访表或者索引,间接就能失去后果, 如 explain select NOW()




<font color="#4682B4"> 6.prossible_keys</font>


可能应用到的索引



<font color="#4682B4"> 7.key </font>


真正应用到的索引

select_typeindex_merge时, 这里可能呈现两个以上的索引;

其余的select_type这里只会呈现一个.



<font color="#4682B4"> 8.key_len</font>


查问用到的索引长度(字节数)

如果是单列索引, 那就整个索引长度算进去;

如果是多列索引(即联结索引),那么查问不肯定都能应用到所有的列,用多少算多少.


能够注意下这个列的值, 算一下多列索引总长度, 就可知有没有应用到所有的列.

**另:
key_len只计算where条件用到的索引长度, 而排序和分组就算用到了索引,也不会计算到key_len中.**



<font color="#4682B4"> 9.ref</font>


如果应用常数等值查问, 这里会显示const;

如果是连贯查问, 被驱动表的执行打算这里会显示驱动表的关联字段,

如果是条件应用了表达式或者函数,或者条件列产生了外部隐式转换, 这里可能显示为func



<font color="#FFD700"> 10.rows</font>


十分重要的一个字段


mysql估算的 须要扫描的行数(不是准确值)

通过这个值,能够十分直观地显示 SQL 的效率好坏.

原则上 rows 越小越好.

当存在limit时,会对rows字段产生影响. 倡议在explain时先去除limit



<font color="#4682B4"> 11.filtered</font>


这个字段示意存储引擎返回的数据在server层过滤后, 剩下多少满足查问的记录数量的比例;

留神是百分比,不是具体记录数.



<font color="#FFD700"> 12.Extra</font>


十分重要的一个字段


explain 中的很多额定信息会在 Extra 字段显示, 常见的有以下几种内容:

  • distinct:在select局部应用了distinc关键字
  • <font color="#3CB371">Using filesort:</font> 当 Extra 中有 Using filesort 时, 示意 MySQL 需额定的排序操作(优先内存,内存空间不够则会在磁盘排序), 不能通过索引程序达到排序成果. 个别存在 Using filesort, 都倡议通过优化去掉, 因为这样的查问对机器的资源耗费很大.
  • <font color="#00FF7F">Using index:</font> "笼罩索引扫描", 示意查问在索引树中就可查找所需数据, 不必扫描表数据文件, 往往阐明性能不错. 即不须要进行filesort
  • Using temporary: 查问有应用长期表, 个别呈现于排序, 分组和多表 join 的状况, 查问效率不高, 倡议通过优化去掉.

另外还有

  • using where:在查找应用索引的状况下,须要回表去查问所需的数据
  • using index condition:查找应用了索引,然而须要回表查问数据
  • using index & using where:查找应用了索引,然而须要的数据都在索引列中能找到,所以不须要回表查问数据

using index 好于 using where 好于 using index condition, 不须要回表查问数据,效率最快


在带有order by子句的sql中,要尽可能使extra字段不要呈现Using filesort,而是Using index


举例如何去掉 Using filesort:

explain后果每个字段的含意阐明

mysql 索引type介绍

MySQL优化:定位慢查问的两种办法以及应用explain剖析SQL




limit 会对explain的type产生微小影响

对于order by的优化

具备LIMIT和不具备LIMIT的ORDER BY可能是不同的

file_sort优化器会事后调配固定数量的sort_buffer_size字节。

MySQL 有时会优化具备LIMIT row_count子句而没有HAVING子句的查问:

如果您只抉择LIMIT的几行,则在某些状况下,MySQL 通常会抉择应用全 table 扫描,而 MySQL 通常会应用索引。

如果将LIMIT row_count和ORDER BY联合应用,MySQL 会在找到排序后果的前 row_count 行后立刻进行排序,而不是对整个后果进行排序。如果通过应用索引进行排序,这将十分快。如果必须执行文件排序,则在找到第一个 row_count 之前,将抉择与查问匹配的所有行,但不带有LIMIT子句,并对其中的大多数或全副进行排序。找到初始行后,MySQL 不会对后果集的其余部分进行排序。

如果没有为ORDER BY应用索引,然而也存在LIMIT子句,则优化器可能可能防止应用合并文件,并应用内存中filesort操作对内存中的行进行排序。

参考:

优化 Sequences

Orderby 排序优化

了解mysql的长期表和文件排序

【IT老齐338】MySQL Extra常见信息解析

【大厂文章速读】字节跳动-慢SQL剖析与优化 (extra呈现这几项,肯定要加倍留神)

本文由mdnice多平台公布