mysql之explain

1、explain作用

使用explain可以模拟优化SQL的作用,使用mysql可以处理你的SQL查询语句和链接表,可以分析查询语句和结构的瓶颈,帮助我们使用更好的索引,和写出更好的查询语句

2、explain每列信息

2.1 id

id表示sql语句的执行顺序,id相等时,按照顺序执行,当id不同时,id越大,sql越先执行

2.2 select_type

(1)SIMPLE:简单查询 查询不包含子查询和union。

(2)PRIMARY:复制的查询中最外层的select查询

(3)SUBQUERY: 包含在select中的子查询(不在from子句)。

(4)DERIVED:包含from子句的子查询。mysql会将结果放到一个临时表中,也叫派生表。

(5)UNION:在union中的第二个和随后的select。

(6)UNION RESULT:从union临时表检索结果的select。

2.3 table

表示explain访问的哪一张表

当from子句中有子查询时,table是格式,表示当前查询依赖id=N的查询,于是先执行id=N的查询

当有union时,UNION RESULT的table列的值为 1和2表示union的select行id

2.4 partitions        

当查询到分区时,会显示相应的信息

2.5 type

表示关联类型或者访问类型,即mysql决定如何查询表中的行,查询数据记录的大概范围。

(1)NULL:mysql能够在SQL执行之前分析分解查询语句,在执行阶段用不着在访问表或者索引,例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表,但是这一般访问的频率不高。

(2)const,system:MySQL能够对查询的某部分进行优化并将其转化成一个常量(可以看show warnings的结果)。用于主键索引或唯一索引的所有列与常数比较时,表最多有一个匹配行,读取1次,速度比较快。

(3)eq_ref: 主键索引和唯一索引被链接使用,最多返回一条符合条件的记录

(4)ref:普通索引被链接使用,可以有多个记录被返回

(5)range:范围查询 between > < in等操作

(6)index:扫描全表索引

(7)ALL:全表扫描

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

2.6 possible_key

查询可能使用哪些索引来查找

2.7 key

MYSQL实际上采用哪个索引来优化对该表的访问

如果没有使用索引,则该列是NULL。

2.8 key_len

MYSQL在索引里面使用的字节数,通过这个值可以具体使用了索引中的哪些值

2.9 ref

这一列记录的索引中,表查找值所用到的列或者常量,常见的有:const,字段名

2.10 rows

MYSQL估计需要读取和检测的行数

2.11 EXTRA

表示额外的信息

(1)using index:查询的列被索引覆盖

(2)using where:查询的列不完全被索引覆盖,where筛选条件非索引的前导列。

(3)Using where; Using index: 查询的列被索引覆盖,并且where筛选条件是索引列之一但不是索引的前导列,意味着无法直接通过索引来查找符合条件的数据。

(4)NULL:查询的列未被索引覆盖,并且where筛选条件是索引的前导列,意味着用到了索引,但是部分字段未被索引覆盖,必须通过“回表”来实现,不是纯粹地用到了索引,也不是完全没用到索引。

(5)Using index condition:MySQL 5.6版本开始加入的新特性,与Using where类似,查询的列不完全被索引覆盖,where条件中是一个前导列的范围。

(6)Using temporary:MySQL需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的,首先要想到用索引来优化。

(7)Using filesort:MySQL会对结果使用一个外部索引排序,而不是按照索引次序从表里读取行。此时MySQL会根据连接类型浏览所有符合条件的记录,并保存排序关键字和行指针,然后排序关键字并按顺序检索行信息。这种情况下一般也是要考虑使用索引来优化。

 3、explain最佳实践

3.1最左前缀法则

如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效(后面的字段索引失效)。

mysql之explain_第1张图片

对此表中profession,age,status创建联合索引

mysql之explain_第2张图片

1、索引长度公式

1.所有的索引字段,如果没有设置not null,则需要加一个字节。

2.定长字段,int占四个字节、date占三个字节、char(n)占n个字符。

3.对于变成字段varchar(n),则有n个字符+两个字节。

4.不同的字符集,一个字符占用的字节数不同。latin1编码的,一个字符占用一个字节,gbk编码的,一个字符占用两个字节,utf8编码的,一个字符占用三个字节。

5.索引长度 char()、varchar()索引长度的计算公式:

Character Set:utf8mb4=4,utf8=3,gbk=2,latin1=1) * 列长度 + 1(允许null) + 2(变长列)

 此图中索引长度为42,计算方式为:36 +2+4=42 此为索引的长度

profession varchar(11)  长度为 3*11+1+2

age tinyint unsigned  长度为2

status char(1)  长度为4

 key_len=38说明索引只使用了profession和age

  key_len=36说明索引只使用了profession,跳过status不会生效

key_len=0 说明没有使用索引,索引失效

 

大家可以看一下,上面的sql语句是否索引生效了

答案是肯定的,因为key_len=42,说明所有的索引都已经生效,和生效顺序无关。

3.2 范围查找

联合索引中如果出现> < 则右侧的索引失效

 key_len为38表示右侧的索引失效。只是生效了profession和age

3.3 索引列运算

不要在索引列上进行运算操作, 索引将失效。

mysql之explain_第3张图片

 通过上述两个查询可知,当范围查询时,phone的索引失效。

3.4 字符串不加引号失效

字符串类型字段使用时,不加引号,索引将失效。

mysql之explain_第4张图片

 通过上述两个查询可知,status没有加引号 则索引失效

3.5模糊查询

如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。

mysql之explain_第5张图片

  通过上述两个查询可知,头部加%的,索引都失效了

3.6 or连接条件

用or分割开的条件, 如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会 被用到。

mysql之explain_第6张图片

上述age没有索引,则导致id和phone索引失效

mysql之explain_第7张图片

  上述age加上索引,则id和phone索引有效

3.7数据分布影响

如果MySQL评估使用索引比全表更慢,则不使用索引。

mysql之explain_第8张图片

 经过测试我们发现,相同的SQL语句,只是传入的字段值不同,最终的执行计划也完全不一样,这是为 什么呢?

就是因为MySQL在查询时,会评估使用索引的效率与走全表扫描的效率,如果走全表扫描更快,则放弃 索引,走全表扫描。 因为索引是用来索引少量数据的,如果通过索引查询返回大批量的数据,则还不 如走全表扫描来的快,此时索引就会失效。

总结:

1、联合索引按照最左匹配原则,在写select语句时要主要索引的使用,防止索引失效。

2、索引失效的情况有:范围查找,索引列运算,字符串不加引号,模糊查询,or连接条件,数据分布影响。

你可能感兴趣的:(mysql,mysql,数据库)