explain执行计划中的type字段实践

265 阅读2分钟

前言

前段时间,背八股文背到了mysql中的执行计划,其中type字段有几种不同的类型,只知道有几种,但很多都没有实践过,今天简单通过两张表,建立一些简单的索引,去实践一下这几个字段,到底是怎么出现的。

准备工作

首先创建了两个简单的表:

CREATE TABLE `user`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NULL,
  `sex` varchar(1) NULL,
  `age` int(11) NULL,
  PRIMARY KEY (`id`)
);
CREATE TABLE `address`  (
  `id` int(0) NOT NULL,
  `user_id` int(0) NULL,
  `address` varchar(255) NULL,
  PRIMARY KEY (`id`)
)

然后往表中插入数据:

INSERT INTO `user`(`id`, `name`, `sex`, `age`) VALUES (1, 'xx', '女', 27);
INSERT INTO `address`(`id`, `user_id`, `address`) VALUES (1, 1, '中国-重庆');

explain之type

EXPLAIN SELECT * FROM `user`;

我们知道sql的执行计划中,有一个type字段,代表了sql使用索引的情况,主要包含以下类型:

1.system

整张表只有一行数据,且存储引擎为MyISAM

  • 当存储引擎为InnoDB时,explain中的type字段为:ALL,即全表扫描
  • 执行这条sql语句将存储引擎改为MyISAM:alter table user ENGINE = MyISAM;
  • 执行 EXPLAIN SELECT * FROM user;
  • 再次查看上面的sql语句的执行计划,其中的type字段已经变成了 system

1645499365(1).png

2.const

表中最多只有一行数据匹配,sql使用了主键或者唯一索引

  • 将存储引擎改到InnoDB:alter table user ENGINE = INNODB;
  • 执行 EXPLAIN SELECT * FROM user where id = 1;
  • 由于id是主键,所以看到type字段为 const

1645499272(1).png

3.eq_ref

每次与之前的表合并都在该表读取一行,特点是使用=,而且索引的所有部分都参与join且索引是主键或非空唯一键的索引

  • 主键索引(primary key)或者非空唯一索引(unique not null)等值扫描
  • 执行 EXPLAIN SELECT user.name,address.address FROM user,address WHERE user.id = address.user_id ;
  • 可以看到 user 表的type字段为 eq_ref
4.ref

使用了普通索引

  • 首先在user表的name字段建立一个普通索引,执行 ALTER TABLE user ADD INDEX name(name) USING BTREE;
  • 执行 EXPLAIN SELECT * FROM user WHERE name = 'xx' ; ,可以看到type字段为 ref

1645498802(1).png

5.fulltext

使用了全文索引

  • 删除之前在name字段上建立的索引
  • 在name字段上添加全文索引 ALTER TABLE user ADD FULLTEXT INDEX ft_stu_name (name);
  • 执行 EXPLAIN SELECT * FROM user WHERE MATCH(name) AGAINST('x');
  • 可以看到type字段为 fulltext

1645498909(1).png

6.ref_or_null

跟 ref 类型类似,只是增加了 null 值的判断

7.range

索引范围查询,常用于使用了=,<>,>,<,IS NULL,IN等运算符的查询中

  • 在user表的age字段上添加普通索引:ALTER TABLE user ADD INDEX ft_age(age);
  • 执行 EXPLAIN SELECT * FROM user WHERE age > 20;,看到type字段为 range

1645498953(1).png

8.index:索引全表扫描,把索引从头到尾扫一遍
  • 执行 EXPLAIN SELECT name FROM user; ,看到type字段为 index

1645499009(1).png

9.all

全表扫描,性能最差

  • 查询所有:EXPLAIN SELECT * FROM user ,type 为 all

1645499058(1).png