Mysql Explain之type详解

select version():5.7.21html

EXPLAIN 是什么

MySQL 提供了一个 EXPLAIN 命令, 它能够对 SQL 语句进行分析, 并输出 SQL 执行的详细信息, 以供开发人员针对性优化.mysql

例如分析一条 SELECT 语句sql

EXPLAIN SELECT * FROM `user` WHERE id = 1 
复制代码

explain-type

EXPLAIN 结果中的type字段

Tips:常见的扫描方式后端

  • system:系统表,少许数据,每每不须要进行磁盘IO
  • const:常量链接
  • eq_ref:主键索引(primary key)或者非空惟一索引(unique not null)等值扫描
  • ref:非主键非惟一索引等值扫描
  • range:范围扫描
  • index:索引树扫描
  • ALL:全表扫描(full table scan)

type扫描方式由快到慢

system > const > eq_ref > ref > range > index > ALL
复制代码

1.system

explain-type

上例中,从系统库mysql的系统标proxies_priv里查询数据,这里的数据在Mysql服务启动时候已经加载在内存中,不须要进行磁盘IO。bash

官方文档中的解释:该表只有一行(=系统表)。这是const联接类型的特例测试

2.const

模拟数据
create table user (
  id int primary key,
  name varchar(20)
)engine=innodb;

insert into user values(1,'ar414');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
insert into user values(4,'wangwu');
复制代码
Explain分析结果

explain-type

上例中id是主键(primary key),链接部分是常量1,经过索引一次就能找到,速度很是快优化

场景:ui

  • 命中主键(primary key)或者惟一索引(unique)
  • 被链接的部分是一个常量值(const)

3.eq_ref

模拟数据
create table user (
  id int primary key,
  name varchar(20)
)engine=innodb;

insert into user values(1,'ar414');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
insert into user values(4,'wangwu');

create table user_balance (
  uid int primary key,
  balance int
)engine=innodb;

insert into user_balance values(1,100);
insert into user_balance values(2,200);
insert into user_balance values(3,300);
insert into user_balance values(4,400);
insert into user_balance values(5,500);
复制代码
Explain分析结果

explain-type

上例中对于前表user表中的每一行(row),对应后user_balance表只有一行被扫描,这类扫描的速度也很是的快spa

场景:3d

  1. 联表(join)查询
  2. 命中主键(primary key)或者非空惟一索引(unique not null)
  3. 等值链接

4.ref

模拟数据

同eq_ref模拟数据区别:user_balance表中的主键索引改成普通索引

create table user (
  id int primary key,
  name varchar(20)
)engine=innodb;

insert into user values(1,'ar414');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
insert into user values(4,'wangwu');

create table user_balance (
  uid int,
  balance int,
  index(uid)
)engine=innodb;

insert into user_balance values(1,100);
insert into user_balance values(2,200);
insert into user_balance values(3,300);
insert into user_balance values(4,400);
insert into user_balance values(5,500);
复制代码
Explain分析结果

联表查询

explain-type

因为后表使用了普通非惟一索引,对于前表user表的每一行(row),后表user_balance表可能有多于一行的数据被扫描

单表查询

explain-type

当id改成普通非惟一索引后,常量的链接查询,也由const降级为了ref,由于非惟一索引因此有多于一行的数据被可能被扫描

ref每一次匹配可能有多行数据返回,虽然它比eq_ref要慢,但它仍然是一个很快的join类型

场景:

  • 联表查询
  • 普通非惟一索引

5.range

模拟数据
create table user (
  id int primary key,
  name varchar(20)
)engine=innodb;

insert into user values(1,'ar414');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
insert into user values(4,'wangwu');
insert into user values(5,'zhaoliu');
复制代码
Explain分析结果

between

explain-type

in

explain-type

>,>=,<,<=

explain-type

range比较好理解,它是索引上的范围查询,它会在索引上扫码特定范围内的值

6.index

话外音:当前测试表为InnoDb,MyISAM 内置了一个计数器,count()时它直接从计数器中读

explain-type

index类型,须要扫描索引上的所有数据,它仅比全表扫描快一点

7.ALL

模拟数据
create table user (
  id int,
  name varchar(20)
)engine=innodb;

insert into user values(1,'ar414');
insert into user values(2,'zhangsan');
insert into user values(3,'lisi');
insert into user values(4,'wangwu');
insert into user values(5,'zhaoliu');
复制代码
Explain分析结果

explain-type

若是id上不建索引,则全表扫描

总结

  • type类型从快到慢:system>const>eq_ref>ref>range>index>ALL
  • 做为一名合格的后端开发者应该熟悉掌握Explain
  • 结合业务创建正确索引,而不是每一个字段创建索引(滥用)
相关文章
相关标签/搜索