在使用MySQL进行查询时,我们经常会遇到SQL执行没有按照我们预想的那样去使用某个索引优化查询,那怎么解决这个问题呢?
对于这个问题,MySQL给我们准备了三个方法,这三个方法可以帮助我们让SQL执行按照我们预想的那样去选择索引。今天我们就针对这三个方法分别来说说吧!
- use index:在你查询语句表名的后面,添加use index来提供你希望mysql去参考的索引列表,就可以让mysql不再考虑其他可用的索引。如:select * from table use index(name,age);
- IGNORE INDEX: 提示会禁止查询优化器使用指定的索引。在具有多个索引的查询时,可以用来指定不需要优化器使用的那个索引,还可以在删除不必要的索引之前在查询中禁止使用该索引。如:select * from table ignore index(name,age);
- force index:强制mysql使用一个特定的索引。一般情况下mysql会根据统计信息选择正确的索引,但是当查询优化器选择了错误的索引或根本没有使用索引的时候,这个提示将非常有用。
注意:use/ignore/force index(index) 括号里的index是索引名,而不是列名。而且后面必须要加上where条件
现在我们已经了解了MySQL提供的指定索引的三个方法,接下来我们就针对这三个方法来实验一下具体的操作及结果吧!
准备表
create table `test`( `id` int UNSIGNED primary key auto_increment, `a` int(11) NOT NULL DEFAULT '0' COMMENT '测试字段a', `b` int UNSIGNED not null default 0 comment '测试字段b', `c` int UNSIGNED not null default 0 comment '测试字段c', index a_index(`a`), index b_index(`b`), index c_index(`c`) )engine=innodb default charset utf8 comment '测试表';
复制
我们可以添加一些测试数据,将下面的SQL重复执行100遍
insert into test(a,b,c) values (1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7),(8,8,8),(9,9,9),(11,11,11);
复制
有了数据后,我们再来看看具体的测试结果吧
1. use index()
在没有指定索引的情况下,SQL会如何执行呢?
从上面的结果可以看出这种方式没有使用索引,会导致全表扫描
2. use index(a)
只指定一个索引时SQL是否走索引呢?使用的索引是哪一个?
由上面的SQL分析可以看出,where条件中有索引字段而【use index】指定了其他索引时,索引失效。但是【use index】指定的索引的字段存在where条件中,指定的索引才会生效,还会导致全表扫描。
3. use index(a) use use index(b)
上面的SQL同时指定了两个索引,SQL又会怎么去执行呢?
由上面的SQL分析可以看出,使用【use index】多次指定索引和一次指定索引效果一样,主要还是要看指定的索引关联的字段是否存在where条件中,存在索引生效,否则不生效,还会导致全表扫描。
4. use index(a) ignore index(a) use use index(b)
同时指定两个索引后又禁用了其中一个索引,这样的SQL又会如何去执行呢?
由上面的SQL分析结果:从前两个SQL可以看出,不管【ignore index】的位置在哪里,只要设置了禁用的索引,那这个索引就会失效,如果禁用的索引关联的字段与where条件中索引字段相同,即使指定了其他所有,所有索引都将失效,从而导致全表扫描。这一点和上面第三个测试结果一样
5. force index()
【force index】是强制使用索引
分析结果如下:
从第一条SQL可以看出【force index】必须设置索引名,否则就会报错。
从第二条SQL可以看出,使用了【force index】就不能再使用【use index】指定其他索引,否则会报错。
如果【force index】强制使用的索引关联的字段不在where条件中,此时【force index】强制指定的索引失效,还会导致全表扫描。
如果【force index】强制索引关联的字段在where条件中,此时就会使用强制设置的索引。如下图所示:
总结一下:
1,【use index】没有指定索引会导致全表扫描,指定的索引关联的字段不在where条件中依然不使用索引,导致全表扫描。所以指定索引时注意索引关联的字段是否在where条件中。
2,【ignore index】必须设置索引名,否则会报错。禁用的索引一定导致索引失效,即使使用【use index】重新指定该索引也无效
3,【force index】必须指定索引名。强制指定的索引关联的字段不在where条件中,所有索引都将失效。而且不能与【use index】同时使用
希望这篇文章可以帮到正在阅读的你,如果觉得此文对你有帮助,可以分享给你身边的朋友,同事,你关心谁就分享给谁,一起学习共同进步~~~
欢迎关注我的公众号【编程经验共享】,第一时间一起学习新知识!
————————————————————————————
公众号:编程经验共享
墨天轮:https://www.modb.pro/u/545037
个人博客:https://www.motui8.cn/
————————————————————————————