文章目录
准备
注!以下都是在mysql-8.0.21版本下进行测试的。
执行计划还不熟悉的小伙伴请先学习执行计划:
MySQL高级-索引是个什么东西?explain到底怎么用-MySQL查询优化大全
CREATE TABLE `test_1` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`age` int DEFAULT NULL,
`addr` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_name` (`name`)
);
预先在表中随便插入12条数据。
对主键使用in做查询
in一个数据
explain select * from test_1 where id in (1);
我们发现type是const,相当于mysql对in做了优化,相当于 id = 1了。
in多个数据
explain select * from test_1 where id in (3,9,5);
在这里,in了三个数据,mysql认为是一个范围查询,同样也会使用索引。
in超多个数据
explain select * from test_1 where id in (3,9,5,8,25,54,99,44,12,657,84);
数据表中总共有12条数据,in的条件有了11条,mysql会做一下优化,不使用索引,会走全表扫描。
注:实际生产环境数据量并不会仅仅只几条数据,经过测试,in似乎只要别太多,都会使用range方式,使用索引(在mysql5版本中,会有in的数量限制,超出一定部分就会走全表扫描)。
实际上mysql会做优化,使用它认为性能更快的方式进行查询。
对非主键索引使用in
in一个数据
explain select * from test_1 where name in ('zhangsan');
我们发现,in一个字段相当于name =‘zhangsan’,mysql对其做了优化,是走索引的。
in多个数据
explain select * from test_1 where name in ('zhangsan','list','wangwu');
还是走的索引。
in超多个数据
explain select * from test_1 where name in ('zhangsan','list','wangwu','zhanfgsan','lisadst','wangdswu','lareist','wangwussdaf','zhanfdsafgsan','lisadgdst','wangdswdfagu');
和主键的用法是一样的。
对索引的"区分度"低的字段使用in(类似性别、状态等等)
经测试,和以上相同(感兴趣的可以自己试一下)。
并没有网上一些博文说的,mysql会做优化,对于索引区分度低的字段会做优化,直接走全表扫描。
其实,mysql本身存储并没有索引区分度这一说,都是按照正常字段来使用索引的!
(有问题还请在评论区指正)
连表查询使用in
经测试,和以上相同(感兴趣的可以自己试一下)。
总结
mysql-8.0.21对于in的使用还是很友好的,正常状态下in都会走索引,除非使用超多的in(基本快要赶上表数据量)才不会走索引。
所以,日常开发中,放心使用in,但是不能in了太多的数据喔~
mysql-5.5.40与mysql-8.0.21使用in的变化(重要!)
亲测!
explain select * from test_1 where id in (1,11,10,7,9);
以上sql,同样的数据,在mysql-8.0.21版本会使用range,走索引。
但是!在mysql-5.5.40,是不走索引的!!!!
所以,在使用低版本mysql的时候,一定要注意in的数量,否则,一不小心就全表扫描了!
但是mysql8版本下,in就友好很多,可以放心使用!