SQL索引失效情况

索引失效情况

首先准备tb_user表如下:
在这里插入图片描述
其中tb_user的索引情况如下:

在这里插入图片描述

1.索引列运算

在索引列上进行运算操作,索引将失效。

由上面索引表知还有一个索引,是phone字段的单列索引
在这里插入图片描述

A. 当根据phone字段进行等值匹配查询时, 索引生效。

   explain select * from tb_user where phone = '17799990015';

在这里插入图片描述
B. 当根据phone字段进行函数运算操作之后,索引失效。

explain select * from tb_user where substring(phone,10,2) = '15';

在这里插入图片描述

2.字符串不加引号

字符串类型字段使用时,不加引号,索引将失效。
接下来,我们通过两组示例,来看看对于字符串类型的字段,加单引号与不加单引号的区别:

explain select * from tb_user where profession = '软件工程' and age = 31 and status = '0';
explain select * from tb_user where profession = '软件工程' and age = 31 and status = 0;

在这里插入图片描述

explain select * from tb_user where phone = '17799990015';
explain select * from tb_user where phone = 17799990015;

在这里插入图片描述
经过上面两组示例,我们会明显的发现,如果字符串不加单引号,对于查询结果,没什么影响,但是数
据库存在隐式类型转换,索引将失效。

3.模糊查询

如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。
接下来,我们来看一下这三条SQL语句的执行效果,查看一下其执行计划:
由于下面查询语句中,都是根据profession字段查询,符合最左前缀法则,联合索引是可以生效的,
我们主要看一下,模糊查询时,%加在关键字之前,和加在关键字之后的影响。

explain select * from tb_user where profession like '软件%';
explain select * from tb_user where profession like '%工程';
explain select * from tb_user where profession like '%工%';

在这里插入图片描述
经过上述的测试,我们发现,在like模糊查询中,在关键字后面加%,索引可以生效。而如果在关键字
前面加了%,索引将会失效。

4.or连接条件

用or分割开的条件, 如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会
被用到

explain select * from tb_user where id = 10 or age = 23;
explain select * from tb_user where phone = '17799990017' or age = 23;

在这里插入图片描述
由于age没有索引,所以即使id、phone有索引,索引也会失效。所以需要针对于age也要建立索引。
然后,我们可以对age字段建立索引

create index idx_user_age on tb_user(age);

在这里插入图片描述
建立了索引之后,我们再次执行上述的SQL语句,看看前后执行计划的变化。
在这里插入图片描述
最终,我们发现,当or连接的条件,左右两侧字段都有索引时,索引才会生效。
## 5.数据分布影响
如果MySQL评估使用索引比全表更慢,则不使用索引。

explain select * from tb_user where phone >= '17799990005';
explain select * from tb_user where phone >= '17799990015';

在这里插入图片描述
经过测试我们发现,相同的SQL语句,只是传入的字段值不同,最终的执行计划也完全不一样,这是为什么呢?
就是因为MySQL在查询时,会评估使用索引的效率与走全表扫描的效率,如果走全表扫描更快,则放弃索引,走全表扫描。 因为索引是用来索引少量数据的,如果通过索引查询返回大批量的数据,则还不如走全表扫描来的快,此时索引就会失效。

接下来,我们再来看看 is null 与 is not null 操作是否走索引。
执行如下两条语句 :

explain select * from tb_user where profession is null;
explain select * from tb_user where profession is not null;

在这里插入图片描述
接下来,我们做一个操作将profession字段值全部更新为null。

update tb_user set profession = null;

在这里插入图片描述
然后,再次执行上述的两条SQL,查看SQL语句的执行计划。
在这里插入图片描述

最终我们看到,一模一样的SQL语句,先后执行了两次,结果查询计划是不一样的,为什么会出现这种现象,这是和数据库的数据分布有关系。查询时MySQL会评估,走索引快,还是全表扫描快,如果全表扫描更快,则放弃索引走全表扫描。 因此,is null 、is not null是否走索引,得具体情况具体
分析,并不是固定的。

猜你喜欢

转载自blog.csdn.net/bigBbug/article/details/129939651
今日推荐