0
点赞
收藏
分享

微信扫一扫

MySQL explain SQL 分析详解

Gaaidou 2022-04-15 阅读 74
mysql

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 值不同,内层查询先执行
id 值不同
情况2:id 值相同,t2 表先执行,t1 表后执行
id 值相同



select_type 列

  • sample
    最简单的查询类型,不包含 union/union all 和子查询
    sample
  • primary:
    若查询包含复杂的子查询,则最外层的查询将被标记为 primary
    primary
  • subquery:
    如上图的查询,在 select 出现的查询与下图的在 where 出现的查询,都会标记上 SUBQUERY subquery
    那么这里多提一下,DEPENDENT SUBQUERYSUBQUERY 的区别:
    先看看官方的定义
    SUBQUERY:子查询中的第一个SELECT
    DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询
    结合上面的结果,可以知道 DEPENDENT SUBQUERY 的查询是依赖外部传入的 id 进行关联,加入外层查询有 100 万条数据,那么内层也需要查询 100 万次(惊呆了),这样的查询的非常慢的,必须要进行优化,看看是否能使用 join 代替;SUBQUERY 很明显就是普通的子查询意思了.
  • derived:
    派生表,表示在 from 出现的子查询,如下所示:
    derived
    由于 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
  • union result:
    用来从匿名临时表里检索结果的 select 被标记为 union result,如上图所示

table 列

在这里插入图片描述


partitions 列


* type 列
  • system: 是 const 的一个特例,当表只有一条数据时为此类型,不过一张表只有一条数据这种情况十分罕见,了解一下即可

  • const: 在单表中通过主键或者唯一索引能精确匹配到一条数据‌
    const

  • eq_ref:多表查询,匹配到一条数据‌
    eq_ref

  • ref:索引查找,不使用唯一索引,使用普通索引或者唯一性索引的部分前缀(like),索引要和某个值相比较,可能会找到多个符合条件的行。简而言之就是能通过索引查询到多条记录
    在这里插入图片描述

  • range:范围扫描,当使用 >、<、>=、<=、in、between 等关于范围操作时会使用到 range,前提是使用到索引来检索数据。
    range

  • index 遍历整棵 B+ 树的所有索引节点‌,跟 all 差不多,比 all、 快一些
    index

  • 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

举报

相关推荐

0 条评论