注册

最完整的Explain总结,SQL优化不再困难!

在 select 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,执行查询时,会返回执行计划的信息,而不是执行这条SQL(如果 from 中包含子查询,仍会执行该子查询,将结果放入临时表中)

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


CREATE TABLE `actor` (
`id` int(11) NOT NULL,
`name` varchar(45) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE `film_actor` (
`id` int(11) NOT NULL,
`film_id` int(11) NOT NULL,
`actor_id` int(11) NOT NULL,
`remark` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_film_actor_id` (`film_id`,`actor_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

两个变种

explain extended

会在 explain 的基础上额外提供一些查询优化的信息。

紧随其后通过 show warnings 命令可以 得到优化后的查询语句,从而看出优化器优化了什么。

额外还有 filtered 列,是一个半分比的值,rows * filtered/100 可以估算出将要和 explain 中前一个表进行连接的行数(前一个表指 explain 中的id值比当前表id值小的表)

mysql> explain extended select * from film where id = 1;

fb490c8699ea454c84ba2c0718c8c842~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp

mysql> show warnings;

a90d7f826dc64dc68c0d2d2c5cef20be~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp

explain partitions

相比 explain 多了个 partitions 字段,如果查询是基于分区表的话,会显示查询将访问的分区。

id列

id列的编号是 select 的序列号,有几个 select 就有几个id,并且id的顺序是按 select 出现的顺序增长的。


一般是使用了覆盖索引(索引包含了所有查询的字段)。对于innodb来说,如果是辅助索引性能会有不少提高

mysql> explain select film_id from film_actor where film_id = 1;

Using where

查询的列未被索引覆盖,where筛选条件非索引的前导列

mysql> explain select * from actor where name = 'a';

Using where Using index

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

mysql> explain select film_id from film_actor where actor_id = 1;

NULL

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

mysql>explain select * from film_actor where film_id = 1;

Using index condition

与Using where类似,查询的列不完全被索引覆盖,where条件中是一个前导列的范围;

mysql> explain select * from film_actor where film_id > 1;

Using temporary

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

  1. actor.name没有索引,此时创建了张临时表来distinct

mysql> explain select distinct name from actor;
  1. film.name建立了idx_name索引,此时查询时extra是using index,没有用临时表

mysql> explain select distinct name from film;

Using filesort

mysql 会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。

此时mysql会根据联接类型浏览所有符合条件的记录,并保存排序关键字和行指针,然后排序关键字并按顺序检索行信息。

这种情况下一般也是要考虑使用索引来优化的。

  1. actor.name未创建索引,会浏览actor整个表,保存排序关键字name和对应的id,然后排序name并检索行记录。

mysql> explain select * from actor order by name;
  1. film.name建立了idx_name索引,此时查询时extra是using index

mysql> explain select * from film order by name;

作者:程序员段飞
来源:https://juejin.cn/post/7074030240904773645

0 个评论

要回复文章请先登录注册