前言
前段时间,背八股文背到了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
2.const
表中最多只有一行数据匹配,sql使用了主键或者唯一索引
- 将存储引擎改到InnoDB:
alter table user ENGINE = INNODB; - 执行
EXPLAIN SELECT * FROM user where id = 1; - 由于id是主键,所以看到type字段为
const
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
5.fulltext
使用了全文索引
- 删除之前在name字段上建立的索引
- 在name字段上添加全文索引
ALTER TABLE user ADD FULLTEXT INDEX ft_stu_name (name); - 执行
EXPLAIN SELECT * FROMuserWHERE MATCH(name) AGAINST('x'); - 可以看到
type字段为fulltext
6.ref_or_null
跟 ref 类型类似,只是增加了 null 值的判断
7.range
索引范围查询,常用于使用了=,<>,>,<,IS NULL,IN等运算符的查询中
- 在user表的age字段上添加普通索引:
ALTER TABLE user ADD INDEX ft_age(age); - 执行
EXPLAIN SELECT * FROMuserWHERE age > 20;,看到type字段为range
8.index:索引全表扫描,把索引从头到尾扫一遍
- 执行
EXPLAIN SELECT name FROM user;,看到type字段为index
9.all
全表扫描,性能最差
- 查询所有:
EXPLAIN SELECT * FROM user,type 为all