mysql 学习与提高5:explain命令详解

目录

Explain 简介

Explain 使用

Explain 字段

1. id字段

2.select_type

3.table

4.type

5.possible_keys

6.key

7.key_len

8.ref

9.rows

10.extra

注意事项


Explain 简介

Explain 提供了 MySQL 如何执行 SQL 语句的信息,通过这些信息,可以对 SQL 语句做相应的优化,提高执行效率。

Explain 使用

调用 Explain,只需要在 SQL 语句前添加 explain 关键字即可。

一般情况下,添加 explain 关键字后,认为 MySQL 不会执行查询,但是如果在 from 子句中包含子查询,那么 MySQL 实际上会执行子查询,将其子查询的结果放在一个临时表中,然后完成外层查询优化。

MySQL 5.6 之前的版本,只允许解释 select 语句,从 MySQL 5.6 开始,非 select 语句也可以被解释了。

Explain 字段

调用 Explain 后,MySQL 会返回一行或者多行记录,通过这些记录就可以知道 SQL 语句的执行情况了。

例如:执行语句

EXPLAIN select * from student where name = 'Bill'

 

每行记录都包含了以下几个字段

  • id:执行编号,标识 select 所属的行
  • select_type:select 查询的类型
  • table:查询的是哪个表
  • partitions:匹配的分区
  • type:关联类型,索引类型
  • possible_keys:该查询可以选用的索引
  • key:该查询选用的索引
  • key_len:索引中使用的字节数
  • ref:显示上述表的连接匹配条件,即哪些列或常量被用于查询索引列上的值
  • rows:估计为了找到所需行而要读取的行数
  • filtered:按表条件过滤的行的百分比
  • Extra:额外的信息

接下来我们逐个进行讲解

1. id字段

  •  id值相同,从上往下 顺序执行。  
  • id值不同:id值越大越优先查询 (本质:在嵌套子查询时,先查内层 再查外层)
  • id值有相同,又有不同: id值越大越优先;id值相同,从上往下 顺序执行

注意:我们发现,表的执行顺序会因为表中数据的个数改变而改变,这是什么原因呢?

假设我们有 a(4)  b(3)  c(3)三种表,括号内的是其数据个数。

当执行语句 select * from a,b,c时

若执行顺序为  b--- c--- a  时,根据笛卡尔积  3 * 2 = 6 * 4 = 24 ,中间结果 6 需要占用存储空间进行存储

若执行顺序为  a--- b--- c  时,根据笛卡尔积  4 * 3 =12 * 2 = 24 ,中间结果12需要占用存储空间进行存储

这两种最后的执行结果是一样的,但是前一种顺序比后一种顺序的中间结果更小,意味着需要更小的存储空间,所以mysql会自动对表的执行顺序进行调整,数据少的表先查询。

2.select_type

select_type表示了查询的类型,它的常用取值有

  • SIMPLE, 表示此查询不包含 UNION 查询或子查询
  • PRIMARY, 表示此查询是最外层的查询
  • UNION, 表示此查询是 UNION 的第二或随后的查询
  • DEPENDENT UNION, UNION 中的第二个或后面的查询语句, 取决于外面的查询
  • UNION RESULT, UNION 的结果
  • SUBQUERY, 子查询中的第一个 SELECT
  • DEPENDENT SUBQUERY: 子查询中的第一个 SELECT, 取决于外面的查询. 即子查询依赖于外层查询的结果.

3.table

表示查询涉及的表或衍生表

//执行如下多表查询
EXPLAIN SELECT * FROM teacher t,course c where t.t_cid = c.c_id;

 

4.type

该列称为关联类型或者访问类型,它指明了 MySQL 决定如何查找表中符合条件的行,同时为判断查询是否高效提供了重要的依据。

以下为常见的取值

  • ALL:全表扫描,这个类型是性能最差的查询之一。通常来说,我们的查询不应该出现 ALL 类型,因为这样的查询,在数据量最大的情况下,对数据库的性能是巨大的灾难。
  • index:全索引扫描,和 ALL 类型类似,只不过 ALL 类型是全表扫描,而 index 类型是扫描全部的索引,主要优点是避免了排序,但是开销仍然非常大。如果在 Extra 列看到 Using index,说明正在使用覆盖索引,只扫描索引的数据,它比按索引次序全表扫描的开销要少很多。
  • range:范围扫描,就是一个有限制的索引扫描,它开始于索引里的某一点,返回匹配这个值域的行。这个类型通常出现在 =、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN、IN() 的操作中,key 列显示使用了哪个索引,当 type 为该值时,则输出的 ref 列为 NULL,并且 key_len 列是此次查询中使用到的索引最长的那个。
  • ref:一种索引访问,也称索引查找,它返回所有匹配某个单个值的行。此类型通常出现在多表的 join 查询, 针对于非唯一或非主键索引, 或者是使用了最左前缀规则索引的查询。
  • eq_ref:使用这种索引查找,最多只返回一条符合条件的记录。在使用唯一性索引或主键查找时会出现该值,非常高效。
  • const、system:该表至多有一个匹配行,在查询开始时读取,或者该表是系统表,只有一行匹配。其中 const 用于在和 primary key 或 unique 索引中有固定值比较的情形。
  • NULL:在执行阶段不需要访问表。

该列取不同值的执行效率依次是

ALL < index < range < ref < eq_ref < const < system < NULL

其中:system,const只是理想情况;实际能达到 ref>range

index 和 all的区别

index:查询全部索引中数据
explain select tid from teacher ; --tid 是索引, 只需要扫描索引表,不需要所有表中的所有数据
all:查询全部表中的数据
explain select cid from course ;  --cid不是索引,需要全表所有,即需要所有表中的所有数据

5.possible_keys

表示 MySQL 在查询时, 能够使用到的索引. 注意, 即使有些索引在 possible_keys 中出现, 但是并不表示此索引会真正地被 MySQL 使用到. MySQL 在查询时具体使用了哪些索引, 由 key 字段决定.

6.key

此字段是 MySQL 在当前查询时所真正使用到的索引.

7.key_len

索引的长度 ;一般用于判断复合索引是否被完全使用  (a,b,c)。

eg:先增加一个表,并把name设为索引

create table test_kl
(
	name char(20) not null default ''
);
alter table test_kl add index index_name(name) ;

 执行explain语句

explain select * from test_kl where name =''

这个60是怎么算的呢? 其实是60 = 20 * 3这样得来的, 20表示每个name占20个字符,3表示在utf8中1个字符站3个字节,所以  便得到了我们的60

 我们继续在原来的基础上再增加一个不为空的name1字段,并设置为索引


alter table test_kl add column name1 char(20) ;  --name1可以为null

alter table test_kl add index index_name1(name1) ;
explain select * from test_kl where name1 ='' ; 

此时ken_len为61,是因为如果索引字段可以为Null,则会使用1个字节用于标识。 

key_len的计算规则如下:

​​​​​

  • 字符串

    • char(n): n 字节长度

    • varchar(n): 如果是 utf8 编码, 则是 3 n + 2字节; 如果是 utf8mb4 编码, 则是 4 n + 2 字节.

  • 数值类型:

    • TINYINT: 1字节

    • SMALLINT: 2字节

    • MEDIUMINT: 3字节

    • INT: 4字节

    • BIGINT: 8字节

  • 时间类型

    • DATE: 3字节

    • TIMESTAMP: 4字节

    • DATETIME: 8字节

  • 字段属性: NULL 属性 占用一个字节. 如果一个字段是 NOT NULL 的, 则没有此属性.

8.ref

注意与type中的ref值区分。作用: 指明当前表所 参照的 字段。
select ....where a.c = b.x ;(其中b.x可以是常量,const)

9.rows

rows 也是一个重要的字段. MySQL 查询优化器根据统计信息, 估算 SQL 要查找到结果集需要扫描读取的数据行数.
这个值非常直观显示 SQL 的效率好坏, 原则上 rows 越少越好.

10.extra

该列显示了有关 MySQL 如何解析查询的其它信息。

以下为常见的取值

  • Using index:使用覆盖索引,表示查询索引就可查到所需数据,不用扫描表数据文件,往往说明性能不错。
  • Using Where:在存储引擎检索行后再进行过滤,使用了 where 从句来限制哪些行将与下一张表匹配或者是返回给用户。
  • Using temporary:在查询结果排序时会使用一个临时表,一般出现于排序、分组和多表 join 的情况,查询效率不高,建议优化。
  • Using filesort:对结果使用一个外部索引排序,而不是按索引次序从表里读取行,一般有出现该值,都建议优化去掉,因为这样的查询 CPU 资源消耗大。

注意事项

  • Explain 不会告诉你触发器、存储过程或用户自定义函数对查询的影响情况; 
  • Explain 不会告诉你 MySQL 在查询执行中所做的特定优化; 
  • Explain 只是个近似结果; 
  • Explain 不会显示关于查询的执行计划的所有信息。

猜你喜欢

转载自blog.csdn.net/qq_37410328/article/details/83719890