select version():
5.7.21
html
MySQL 提供了一个 EXPLAIN
命令, 它能够对 SQL
语句进行分析, 并输出 SQL
执行的详细信息, 以供开发人员针对性优化.mysql
例如分析一条 SELECT 语句sql
EXPLAIN SELECT * FROM `user` WHERE id = 1 复制代码
Tips:常见的扫描方式后端
type
扫描方式由快到慢system > const > eq_ref > ref > range > index > ALL
复制代码
上例中,从系统库mysql的系统标proxies_priv里查询数据,这里的数据在Mysql服务启动时候已经加载在内存中,不须要进行磁盘IO。bash
官方文档中的解释:该表只有一行(=系统表)。这是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');
复制代码
上例中id是主键(primary key),链接部分是常量1,经过索引一次就能找到,速度很是快优化
场景:ui
主键(primary key)
或者惟一索引(unique)
常量值(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');
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);
复制代码
上例中对于前表user
表中的每一行(row),对应后user_balance
表只有一行被扫描,这类扫描的速度也很是的快spa
场景:3d
联表
(join)查询主键
(primary key)或者非空惟一索引
(unique not null)等值
链接同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);
复制代码
联表查询
因为后表使用了普通非惟一索引
,对于前表user
表的每一行(row),后表user_balance
表可能有多于一行的数据被扫描
单表查询
当id改成普通非惟一索引后,常量的链接查询,也由const降级为了ref,由于非惟一索引因此有多于一行的数据被可能被扫描
ref
每一次匹配可能有多行数据返回,虽然它比eq_ref要慢,但它仍然是一个很快的join类型
场景:
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');
复制代码
between
in
>,>=,<,<=
range比较好理解,它是索引上的范围查询,它会在索引上扫码特定范围内的值
话外音:当前测试表为InnoDb,MyISAM 内置了一个计数器,count()时它直接从计数器中读
index类型,须要扫描索引上的所有数据,它仅比全表扫描快一点
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');
复制代码
若是id上不建索引,则全表扫描