MySQL Version: 8.0.28
简介:
explain
是 MySQL 提供的可以用来查看 SQL 的执行计划的命令, explain
可以与 select、delete、insert、replace、update 等一起使用,不过常用的还是用在 select 比较多,常常用它对 SQL 进行分析,看是否有优化的余地。
通过 explain
命令可以知道以下信息:
- 表的读取顺序
- 数据读取操作的类型(全表扫描还是索引)
- 哪些索引可以使用
- 哪些索引实际使用了
- 表之间的引用
- 每张表有多少行被优化器查询等
基本用法如下:
explain select * from `user`;
explain
结果列
从上图可以看出 explain
共有 12 列,分别是:
id、 select_type、 table、 partitions、 type、 possible_keys、 key、 key_len、 ref、 rows、 filtered、 Extra
接下来对每一列代表的作用进行解释(主要针对 select 情况)。
先建立 3 个表进行测试
表一:用户表
CREATE TABLE `user` (
`id` int NOT NULL,
`name` varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL,
`sex` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_sex` (`sex`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
INSERT INTO `user` values (1, '卢本伟', '男'), (2, 'white', '男'), (2, '五五开', '男');
表二:用户登录日志表
CREATE TABLE `login_history` (
`id` int NOT NULL,
`user_id` int NOT NULL COMMENT '用户 id',
`login_time` datetime NOT NULL COMMENT '登陆时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_login_time` (`login_time`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
insert into login_history
values
(1, 1, now()),
(2, 2, now()),
(3, 3, now());
id 列
情况1:id 值不同,内层查询先执行
情况2:id 值相同,t2 表先执行,t1 表后执行
select_type 列
- sample:
最简单的查询类型,不包含 union/union all 和子查询
- primary:
若查询包含复杂的子查询,则最外层的查询将被标记为 primary
- subquery:
如上图的查询,在 select 出现的查询与下图的在 where 出现的查询,都会标记上 SUBQUERY
那么这里多提一下,DEPENDENT SUBQUERY
与SUBQUERY
的区别:
先看看官方的定义
SUBQUERY:子查询中的第一个SELECT
DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询
结合上面的结果,可以知道DEPENDENT SUBQUERY
的查询是依赖外部传入的 id 进行关联,加入外层查询有 100 万条数据,那么内层也需要查询 100 万次(惊呆了),这样的查询的非常慢的,必须要进行优化,看看是否能使用 join 代替;SUBQUERY
很明显就是普通的子查询意思了. - derived:
派生表,表示在 from 出现的子查询,如下所示:
由于 MySQL 5.7 后对派生表进行优化,会将它合并到外部查询或者临时表,例如上诉查询会合并到外部,变为SELECT * FROM user
,要想得到上面的结果,需要关闭优化,执行以下命令:
set session optimizer_switch='derived_merge=off';
set global optimizer_switch='derived_merge=off';
- union:
位于 union 中第二个及其以后的子查询被标记为 union,第一个就被标记为 primary 如果是 union 位于 from 中则标记为 derived
- union result:
用来从匿名临时表里检索结果的 select 被标记为 union result,如上图所示
table 列
partitions 列
* type 列
-
system: 是 const 的一个特例,当表只有一条数据时为此类型,不过一张表只有一条数据这种情况十分罕见,了解一下即可
-
const: 在单表中通过主键或者唯一索引能精确匹配到一条数据
-
eq_ref:多表查询,匹配到一条数据
-
ref:索引查找,不使用唯一索引,使用普通索引或者唯一性索引的部分前缀(like),索引要和某个值相比较,可能会找到多个符合条件的行。简而言之就是能通过索引查询到多条记录
-
range:范围扫描,当使用 >、<、>=、<=、in、between 等关于范围操作时会使用到 range,前提是使用到索引来检索数据。
-
index 遍历整棵 B+ 树的所有索引节点,跟 all 差不多,比 all、 快一些
-
all: 全表扫描,最糟糕的情况,这种一定要去加索引做优化,理论上是不应该出现的
possible_key 列
key 列
key_len 列
ref 列
rows 列
Extra 列
- Using index:使用覆盖索引,表示查询索引就可查到所需数据,不用回表,说明性能不错。
- Using where:在存储引擎检索行后再进行过滤,就是先读取整行数据,再按 where 条件进行取舍。
- Using temporary:mysql 需要创建一张临时表来处理查询,一般是因为查询语句中有排序、分组、和多表 join 的情况,一般是要进行优化的。
- Using filesort:对结果使用一个外部索引排序,而不是按索引次序从表里读取行,一般有出现该值,都建议优化去掉,因为这样的查询 CPU 资源消耗大。
参考链接:
https://segmentfault.com/a/1190000008131735
https://mp.weixin.qq.com/s/0yddhs4qGEOYNsLznbKPDg
如需转载请注明出处:https://blog.csdn.net/qq_39363204/article/details/123980411