共计 1506 个字符,预计需要花费 4 分钟才能阅读完成。
工作中,常常遇到这样的问题,我明明在 MySQL 表下面加了索引,为什么执行 SQL 查问的时候却没有用到索引?
同一条 SQL 有时候查问用到了索引,有时候却没用到索引,这是咋回事?
起因可能是索引生效了,生效的起因有以下几种,看你有没有踩过相似的坑?
1. 数据筹备:
有这么一张用户表,在 name 字段上建个索引:
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '姓名',
`age` int DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB COMMENT='用户表';
2. Explain 详解:
想要查看一条 SQL 是否用到索引?用到了哪种类型的索引?
能够应用 explain 关键字,查看 SQL 执行打算。例如:
explain select * from user where id=1;
能够看到 type=const,示意应用了主键索引。
explain 的所有 type 类型如下:
3. 生效起因
1. 数据类型隐式转换
name 字段是 varchar 类型,如果咱们应用数据类型查问,就会产生数据类型转换,尽管不会报错,然而无奈用到索引。
explain select * from user where name='一灯';
explain select * from user where name=18;
2. 含糊查问 like 以 % 结尾
explain select * from user where name like '张 %';
explain select * from user where name like '% 张';
3. or 前后没有同时应用索引
尽管 name 字段上加了索引,然而 age 字段没有索引,应用 or 的时候会全表扫描。
# or 前后没有同时应用索引,导致全表扫描
explain select * from user where name='一灯' or age=18;
4. 联结索引,没有应用第一列索引
如果咱们在(name,age)上,建设联结索引,然而查问条件中只用到了 age 字段,也是无奈用到索引的。
应用联结索引,必须遵循最左匹配准则,首先应用第一列字段,而后应用第二列字段。
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(255) DEFAULT NULL COMMENT '姓名',
`age` int DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`),
KEY `idx_name_age` (`name`,`age`)
) ENGINE=InnoDB COMMENT='用户表';
5. 在索引字段进行计算操作
如果咱们在索引列进行了计算操作,也是无奈用到索引的。
# 在主键索引上进行计算操作,导致全表扫描
explain select * from user where id+1=2;
6. 在索引字段字段上应用函数
如果咱们在索引列应用函数,也是无奈用到索引的。
7. 优化器选错索引
同一条 SQL 有时候查问用到了索引,有时候却没用到索引,这是咋回事?
这可能是优化器抉择的后果,会依据表中数据量抉择是否应用索引。
当表中大部分 name 都是一灯,这时候用 name=’ 一灯 ’ 做查问,还会不会用到索引呢?
索引优化器会认为,用索引还不如全表扫描来得快,罗唆不必索引了。
当然咱们认为优化器优化的不对,也能够应用 force index 强制应用索引。
知识点总结:
文章继续更新,能够微信搜一搜「一灯架构」第一工夫浏览更多技术干货。