explain

explain以一种可视化的形式, 帮我们近似展示SQL底层执行的状态/执行计划

各个结果字段意义

image-20240904112606794

id

id标识符。这是查询中的SELECT的序列号. 我们一般通过id值的大小研究查询中的逻辑顺序. (但是需要注意的是,它不一定完全代表真实绝对的SQL执行顺序, 是一种逻辑上的相对顺序, 在一些特殊操作中未必按照如下说明).

  • id不同时:id值越大,优先级越高,越先被执行

  • id既有相同又有不同时:不同的id值,id值越大,优先级越高,越先被执行; 相同的id值,按照从上到下的顺序执行

select_type

使用的查询类型。如普通查询、联合查询、子查询等

常见类型:

类型 描述
SIMPLE 简单的查询 (查询中不包含子查询或者UNION)
PRIMARY 外层查询 (查询中若包含任何复杂的子部分)
SUBQUERY 子查询
DERIVED 派生表
UNION 一般属于第二个SELECT, 出现在UNION之后,则被标记为UNION
UNION RESULT 从UNION表获取结果的SELECT

table

表名

partitions

分区。只对设置了分区的表有意义,现在是NULL,暂时忽略。

type

显示MySQL访问表的方式(比如访问索引,全表扫描等)

性能从好到坏:

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

常见字段 表示含义
system 系统表,或者极少量数据,往往不需要进行磁盘IO
const 常量连接(常数级时间复杂度, 基本上是命中主键)
eq_ref 多表关联查询时,主键索引或唯一索引作为关联条件进行等值扫描
re f 非主键或者非唯一索引等值扫描
range 范围扫描
index 全索引扫描 (比如修改表中数据, 导致所有索引结构变化)
ALL 全表扫描

possible_keys

SQL执行中有可能用到的索引

  • 这列数据是在SQL在优化器初步解析时生成,随着进一步优化,该列索引不一定使用

key

SQL执行中实际用到的索引

  • 如果为NULL,则没有使用

key_len

↑上面的key占用的字节数

  • 索引类型为int时,占用4字节

  • long占用8字节

  • float占用4字节

  • 若key是非主键索引:

比如索引是一个student_name列

  • 类型为varchar(20)
  • 使用utf8mb4编码(含义是utf8 most bytes 4,所以最多占用4个字节)
  • 允许为null

那么key_len = 20 * 4 + 1(NULL)+ 2 (存储实际数据长度)

展开说说NULL与描述长度

  • 数据允许为null,则需额外占1个字节,所以索引字段最好不要允许为null
  • 在InnoDB存储引擎中,索引中的变长字段通常使用2个字节来存储长度前缀。比如在数据为武松时(在utf8mb4中一个汉字占3字节,所以武松需要占6字节)而那2字节就是用来存储6这个数字。2个字节可表示的最大长度为65535(2^16 - 1)

ref

用于查找行的列或常量

表示将哪个字段或常量和key列所使用的字段进行比较。

rows

优化器预计扫描的行数

这个数字是基于表统计信息(如索引统计、行数估计等)估算的,不是确切值

通常情况下,rows 值越小,意味着查询需要处理的数据量越少,性能越好

filtered

MySQL 预计从该步骤的扫描行中留下的行数,占总扫描行数的比例

单位是百分比,是对rows进一步过滤的比例

  • 举例:如果 rows 是 1000,filtered10.00,表示查询计划预计扫描的行数中大约 10% 会通过 WHERE 子句的过滤条件,则查询返回的行数大约是 1000 * 10% = 100

作用:它帮助评估过滤条件的效率。如果 filtered 值较高,说明大部分行都满足过滤条件;而较低的值则表明大部分行被过滤掉,可能意味着查询需要扫描大量行却只保留少量数据。

Extra

额外信息

image-20240905110216891

显示了MySQL在查询过程中的一些详细信息。

描述
Using filesort 说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取, 也称为文件排序.
Using temporary 使了用临时表保存中间结果,MySQL在对查询结果排序时使用临时表。
USING index 是否用了覆盖索引
Using where 表明使用了where过滤
Impossible where where子句的值总是false,不能用来获取任何元组

更新时间: