MySQL(0) -- Explain执行计划基本介绍及栗子

        • 0. 表创建
        • 1. id列
        • 2. select_type 列
          •  2.1. simple
          •  2.2. primary
          •  2.3. subquery
        •  2.4. derived
          •  2.5. union
          •  2.6. union result
        • 3. table列
        • 4. type列(重要)
          •  4.1. NULL
          •  4.2. const和system
          •  4.3. eq_ref
          •  4.4. ref
          •  4.5. range
          •  4.6. index
          •  4.7. ALL
        • 5. possible_keys列和key列(重要)
        • 6. key_len列(重要)
        • 7. ref列
        • 8. rows列
        • 9. Extra列
          •  9.1 Using index
          •  9.2. Using where
          •  9.4. Using temporary
          •  9.5. Using filesort

使用explain可以模拟优化器执行SQL语句,从而知道MySQL是如何处理你的SQL语句的。

0. 表创建

CREATE TABLE `actor` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `film_id` int(11) DEFAULT NULL,
  `name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_film_id` (`film_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

insert  into `actor`(`id`,`film_id`,`name`,`update_time`) values (1,1,'actor1','2021-05-04 17:14:44'),(2,2,'actor2','2021-05-04 17:17:18'),(3,3,'actor3','2021-05-04 17:17:18'),(4,4,'actor2','2021-05-04 17:17:18');

CREATE TABLE `film` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `remark` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

insert  into `film`(`id`,`name`,`remark`) values (1,'film1',NULL),(2,'film2',NULL),(3,'film3',NULL);

1. id列

  • id列的编号是 select 的序列号,一般有几个 select 就有几个id
  • id的顺序是按 select 出现的顺序增长的
  • id列越大执行优先级越高,越先执行
  • id相同则从上往下执行,id为NULL最后执行
EXPLAIN SELECT NAME FROM actor WHERE film_id = (SELECT id FROM film WHERE NAME = 'film2')

在这里插入图片描述

 先执行后面的子查询(id列越大执行优先级越高,越先执行)

2. select_type 列

  • ​select_type 表示对应行是简单还是复杂的查询
 2.1. simple
  • 简单查询,查询不包含子查询和union。

在这里插入图片描述

 2.2. primary
  • 复杂查询(包含子查询或union)中最外层的 select,就会被标记primary;如下查询actor时,就是primary

MySQL(0) -- Explain执行计划基本介绍及栗子_第1张图片

 2.3. subquery
  • 包含在 select或where 中的子查询(不在 from 子句中);像上图子查询的film表

在这里插入图片描述

 2.4. derived

  • 包含在 from 子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表(derived的英文含义);见下方union result
 2.5. union
  • 第二个select出现在union之后,则被标记union

MySQL(0) -- Explain执行计划基本介绍及栗子_第2张图片

 2.6. union result
  • 从 union 临时表检索结果的 select

MySQL(0) -- Explain执行计划基本介绍及栗子_第3张图片
MySQL(0) -- Explain执行计划基本介绍及栗子_第4张图片

3. table列

  • 表示 explain 的一行正在访问哪个表
  • 当 from 子句中有子查询时,table列是 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询。
  • 当有 union 时,UNION RESULT 的 table 列的值为,2和3表示参与 union 的 select 行id。

MySQL(0) -- Explain执行计划基本介绍及栗子_第5张图片

4. type列(重要)

  • 这一列表示关联类型或访问类型,即MySQL决定如何查找表中的行,查找数据行记录的大概范围。
  • 常见的依次从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL
  • 一般来说,得保证查询达到range级别,最好达到ref
 4.1. NULL
  • mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。
  • 例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表

在这里插入图片描述

 4.2. const和system
  • const表示通过索引一次就能找到,用于 primary key 或 unique key 的所有列与常数比较时
  • system是const的特例,表里只有一条数据,匹配时为system,可忽略

在这里插入图片描述

 4.3. eq_ref
  • 唯一索引扫描,简单的 select 查询不会出现这种 type。
  • primary key 或 unique key 索引键作为关联条件 ,表中只有一条记录与之匹配。

MySQL(0) -- Explain执行计划基本介绍及栗子_第6张图片

 4.4. ref
  • 不使用唯一索引,而是使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行。

MySQL(0) -- Explain执行计划基本介绍及栗子_第7张图片

 film的name是普通索引

 4.5. range
  • 范围扫描通常出现在in(), between ,> ,<, >= 等操作中。使用一个索引来检索给定范围的行。

在这里插入图片描述

 4.6. index
  • 扫描全表索引,这通常比ALL快一些。(index是从索引中读取的,而all是从硬盘中读取)

在这里插入图片描述

  • film的name是普通索引,id是主键索引,通过索引就能获取这两个字段值
  • 如果select * ,那么其他字段不能从索引获取,就需要全表扫描
 4.7. ALL
  • ​ 即全表扫描,意味着mysql需要从头到尾去查找所需要的行。通常情况下这需要增加索引来进行优化了

在这里插入图片描述

5. possible_keys列和key列(重要)

  • possible_keys这一列显示查询可能使用哪些索引来查找。
  • key这一列显示mysql实际采用哪个索引来优化对该表的访问,如果没有使用索引,则该列是 NULL。

在这里插入图片描述

 理论上用到的索引有两个,但实际用主键索引就够了

  • key 显示 NULL 的情况,要么是没建索引,要么是索引失效了。

MySQL(0) -- Explain执行计划基本介绍及栗子_第8张图片

 actor是有主键索引的,这里union就失效了,可以看到possible_keys和key列都为null

6. key_len列(重要)

  • 这一列显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。
  • 计算规则:
     字符串 char(n):n字节长度
     varchar(n):如果是utf-8,则长度 3n + 2 +1,2字节存储字符串长度,允许为null占1字节
     tinyint:1字节
     smallint:2字节
      int:4字节
     bigint:8字节  
     date:3字节
     timestamp:4字节
     datetime:8字节
     允许为null占1字节

在这里插入图片描述

 主键id不为null,为int类型,所以索引使用到的字节数4

在这里插入图片描述

  • name为varchar(20),所以最大60,还有2字节存储字符串长度,此外允许为null占1字节
  • 所以idx_name索引使用到的字节数为60+2+1=63

7. ref列

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

8. rows列

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

9. Extra列

 9.1 Using index

  查询的列被索引覆盖,是性能高的表现。一般是使用了覆盖索引(索引包含了所有查询的字段)。

在这里插入图片描述

 film的name是普通索引,id是主键索引,通过索引就能获取这两个字段值

 9.2. Using where
  • 表示mysql服务器将在存储引擎检索行后再进行过滤。
  • 许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验
  • 因此不是所有带where字句的查询都会显示"Using where"。

在这里插入图片描述

 9.3. NULL

 查询的列未被索引覆盖,并必须通过“回表”来查找,不是纯粹地用到了索引,也不是完全没用到索引

在这里插入图片描述

 用到了主键索引,但是其他字段不能通过索引获取,需要回表去查找

 9.4. Using temporary

 需要创建一张临时表来处理查询。常见于排序、去重、分组

MySQL(0) -- Explain执行计划基本介绍及栗子_第9张图片

 9.5. Using filesort

 ​ MySQL中无法利用索引完成的排序操作称为“文件排序”

在这里插入图片描述

你可能感兴趣的:(SQL,mysql,索引,java,数据库,explain)