不废话,直接上干货。
一,explain 使用
explain 的使用很简单,只需要explain后面跟上你的SQL语句就行了。
explain
select * from ci_configs;
二、explain分析指标

指标:id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra,
下来一一解释下每个指标。
2.1 id
id的话,在我们使用的SQL比较复杂的时候,在MySQL优化器的工作下,我们的SQL语句实际上是被拆分成了多个语句来执行,这时候就会有多个id来区分。
(1) 如果id相同,执行顺序会从上到下执行。
(2) SQL语句中存在子查询,那么id会依次增大。
(3) id值越大,执行优先级越高
2.2 select_type
每个select子句的类型
(1) SIMPLE(简单SELECT,无UNION或子查询等)
(2) PRIMARY(查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY)
(3) UNION(UNION中的第二个或后面的SELECT语句)
(4) DEPENDENT UNION(UNION中的第二个或后面的SELECT语句,取决于外面的查询)
(5) UNION RESULT(UNION的结果)
(6) SUBQUERY(子查询中的第一个SELECT)
(7) DEPENDENT SUBQUERY(子查询中的第一个SELECT,取决于外面的查询)
(8) DERIVED(派生表的SELECT, FROM子句的子查询)
(9) UNCACHEABLE SUBQUERY(一个子查询的结果不能被缓存,必须重新评估外链接的第一行)
2.3 table
当前行数据的表名,有时候并不是真的表名,可以是给查询表起的别名或者系统给的派生表名称,
例如 ed 是别名 ,derived5 是系统给定的派生表名称

2.4 partitions
当前从分区表哪个表分区获取数据,如果不是分区表,则显示为NULL
2.5 type
ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行
index: Full Index Scan,index与ALL区别为index类型只遍历索引树
range:只检索给定范围的行,使用一个索引来选择行
ref: 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值
eq_ref: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件
const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system
NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。

2.6 possible_keys
可能使用的索引键,指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用。
这个里面给出了ed 表里面的所有索引。

2.7 key
我们SQL中实际用到的索引,没有用到索引则为null(要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX)

2.8 key_len
SQL所使用的索引的键的字节数(越短越好),没有索引则为null,如果索引字段允许为null,则增加一个字节

2.9 ref
显示哪些常量或者字段被用于查询索引列键值,以获取表中数据行。
(1) 如果是常量等值查询,则显示为const。 (2) 如果是连接查询,则被驱动表的该字段会显示驱动表的所关联字段。 (3) 如果条件当中使用函数表达式,或者值导致条件字段发生隐式转换,则为func。 (4) 如果没有索引,则为null。

2.10 rows
显示预估需要查询的行数。对InnoDB表来说这是个预估值,并非是个准确值。

2.11 filtered
显示按表条件过滤的表行的估计百分比。

2.12 Extra
该列包含MySQL解决查询的详细信息,有以下几种情况:
(1) Using index:仅查询索引树就可以获取到所需要的数据行,而不需要读取表中实际的数据行。通常适用于select字段就是查询使用索引的一部分,即使用了覆盖索引。 (2) Using index condition:显示采用了Index Condition Pushdown (ICP)特性通过索引去表中获取数据。 (3) Using index for group-by:跟Using index访问表的方式类似,显示MySQL通过索引就可以完成对GROUP BY或DISTINCT字段的查询,而无需再访问表中的数据。 (4) Using where:显示MySQL通过索引条件定位之后还需要返回表中获得所需要的数据。 (5) Impossible WHERE:where子句的条件永远都不可能为真。 (6) Using join buffer (Block Nested Loop), Using join buffer (Batched Key Access):在表联接过程当中,将先前表的部分数据读取到join buffer缓冲区中,然后从缓冲区中读取数据与当前表进行连接。主要有两种算法:Block Nested Loop和Batched Key Access (7) Using MRR:读取数据采用多范围读(Multi-Range Read)的优化策略。 (8) Range checked for each record (index map: N):MySQL在获取数据时发现在没有索引可用,但当获取部分先前表字段值时发现可以采用当前表某些索引来获取数据。 (9) Using temporary:MySQL需要创建临时表来存放查询结果集。通常发生在有GROUP BY或ORDER BY子句的语句当中。 (10) Using filesort:MySQL需要对获取的数据进行额外的一次排序操作,无法通过索引的排序完成。通常发生在有ORDER BY子句的语句当中。
简单来说,这个参数就是给我们一些优化的建议。
三、索引失效场景
(1) 对索引类计算 或者使用函数(例如 substring )都会导致索引失效
(2) 不等于(!= 或者<>)索引失效 字符串类型字段不加引号,索引失效
(3) LIKE 以%开头索引失效 不符合 最左前缀法则
(4) or连接条件:用or分割开的条件, 如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。当or连接的条件,左右两侧字段都有索引时,索引才会生效
(5) 如果MySQL评估使用索引比全表更慢,则不使用索引
四、总结
实际开发过程中我们主要关注几个比较重要的指标:type,key,Extra 就可以了。

