一、Explain的作用?
        Explain关键字可以模拟优化器执行SQL语句,一般用来分析SQL语句为什么执行较慢。用法比较简单,在Select语句之前增加Explain关键词即可。执行之后返回的是执行计划的信息。一般如图所示:

        这里不同版本返回的字段可能有不同,我这里用的是8.0.x的版本:
(旧版本可以试试explain extended 以及explain partitions两个指令,返回的可能会全一点)


二、Explain返回数据每个列代表什么意思?
id:id列的编号是 select 的序列号,有几个 select 就有几个id。
        id列越大执行优先级越高,id相同则从上往下执行,id为NULL最后执行(id为null通常表示对应的操作是额外的辅助操作,例如GROUP BY、DISTINCT、ORDER BY这些操作,可以自己试一下)。

        举个栗子:id为2的先查询,从sql可以看出是先进行子查询。不多赘述


select_type:表示对应行是简单还是复杂的查询。大概有以下几种
        1)simple:简单查询。查询不包含子查询和union
        2)primary:复杂查询中最外层的 select
        3)subquery:包含在 select 中的子查询(不在 from 子句中)
        4)derived:包含在 from 子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表(derived的英文含义)。
        但是这个图from后面有子查询,为啥返回的select_type里面没有derived呢?豆包了一下,发现是被优化器合并了。(这里又延申到另一个问题,sql语句不是直接执行的,是先内部优化再执行。。。MySQL不相信你的技术哈哈,后面学到再详细写吧。。)

        这里可以先关掉优化器,再查询即可,可以看出select_type是由DERIVED类型的。

        关闭和打开合并优化的语句:

set session optimizer_switch='derived_merge=off'; #关闭优化
set session optimizer_switch='derived_merge=on'; #还原,默认就是打开的


        5)union:在 union 中的第二个和随后的 select(如图)


table:表示 explain 的这一行正在访问哪个表。当from有子查询时,格式是的格式,表示当前查询依赖id为N的查询,于是需要先执行id=N的查询。
当有 union 时,UNION RESULT 的 table 列的值为<union1,2>,1和2表示参与 union 的 select 行id。

partition:partition 列表示查询执行时命中的表分区(如果表使用了分区策略)。当表未分区时,该列值为 NULL;若表已分区且查询命中特定分区,则显示实际访问的分区名称。

type:这一列比较重要,代表关联类型或者访问类型,既MySQL决定如何查找表中的行。这里几种类型的效率如下:
        System > Const > ref_eq > ref > range > index > ALL

        也有为NULL的时候:mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表。
详细情况如下:
        1)const:主键或唯一索引等值查询,性能较高,最多就返回一行数据
        2)system:system是const的特殊情况,表里面只有一行数据时,用主键或唯一所以等值查询,性能是type类型里面最高的。
        3)reg_eq:primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。这可能是在const 之外最好的联接类型了,简单的 select 查询不会出现这种 type。
        4)ref:相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行。
        5)range:范围扫描,通常出现在 in(), between ,> ,<, >= 等操作中。使用一个索引来检索给定范围的行。
        6)index:扫描全索引就能拿到结果,一般是扫描某个二级索引,这种扫描不会从索引树根节点开始快速查找,而是直接对二级索引的叶子节点遍历和扫描,速度还是比较慢的,这种查询一般为使用覆盖索引,二级索引一般比较小,所以这种通常比ALL快一些。
        7)all:即全表扫描,扫描你的聚簇索引的所有叶子节点。通常情况下这需要增加索引来进行优化了。

possible_keys:
        1)这一列显示本次查询可能会使用哪些索引来查找。
        2)可能出现 possible_keys 有列,而 key 显示 NULL 的情况,这种情况是因为数据库经过计算,走索引的cost比不走索引更大,所以实际执行不会走索引。(每种方式的cost可以通过trace来查看,具体方法后面讲)
        3)如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查 where 子句看是否可以创造一个适当的索引来提高查询性能,然后用 explain 查看效果。

key:
        这一列显示mysql实际采用哪个索引来优化对该表的访问。
        如果没有使用索引,则该列是 NULL。如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 force index、ignore index。

key_len:
        这一列显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。一般联合索引会用到。比如A、B、C三列创建一个联合索引idx_abc,假设3个列的数据长度都是3,如果key显示的索引是idx_abc,结合key_len列来看,如果显示的是3,代表联合索引的B和C列索引未生效,如果key_len长度为6或者9,依次类推。
一些长度计算情况如下:
        key_len计算规则如下:
        在MySQL 5.0.3及之后的版本中,字符串类型char(n)和varchar(n)中的n表示字符数而非字节数。以UTF-8编码为例:

数字或字母占用1字节
汉字占用3字节
具体存储情况:

char(n):存储汉字时占用3n字节
varchar(n):存储汉字时占用3n+2字节(额外2字节用于存储字符串长度信息)
数值类型存储空间:

tinyint:1字节
smallint:2字节
int:4字节
bigint:8字节
时间类型存储空间:

date:3字节
timestamp:4字节
datetime:8字节
注意事项:
允许为NULL的字段需要额外1字节记录NULL状态
索引最大长度为768字节,当字符串过长时,MySQL会自动采用类似左前缀索引的方式处理

ref:
        这一列显示了在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量),字段名(例:film.id)

rows:
        这一列是mysql估计要读取并检测的行数,注意这个不是结果集里的行数。

filtered:
        该列是一个百分比的值, filtered = 实际取出的行数 / 扫描行数。实际上索引优化的最终目的是扫描尽量少的行数并且扫描到的行数基本上都是满足要求的。极端的情况就是扫描了一行,这一行就是想要的数据,此时rows就是1,filtered就是100.

Extra:
        这一列展示的是额外信息。常见的如下:
        1)Using index:使用覆盖索引。一般是指二级索引的字段能够满足select所要选取的字段。例如建立了table1有field1、field2、field3、field4共4个字段,如果用field2、field3、field4建立了一个联合索引。此时用select * from table1 where xxx(这里条件要满足索引生效条件,否则索引都不生效,更不会产生覆盖索引)是不满足覆盖索引的条件的。select field2,field3,field4 from table where xxx是满足的。
        2)Using where:使用 where 语句来处理结果,并且查询的列未被索引覆盖
        3)Using index condition:表示查询使用了**索引条件下推(Index Condition Pushdown, ICP)**优化技术。该优化允许存储引擎在索引层面提前过滤数据,减少回表操作次数,提升查询效率。
        4)Using temporary:mysql需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的,首先是想到用索引来优化。
        5)Using filesort:将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的。
        6)Select tables optimized away:使用某些聚合函数(比如 max、min)来访问存在索引的某个字段时。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐