mysql知识点整理--索引的使用01

本文详细介绍了MySQL索引的使用,包括最左前缀法则在联合索引中的应用,范围查询的影响,索引在函数运算、隐式转换和模糊查询中的失效情况,以及OR条件和数据分布对索引效果的决定性影响。通过实例展示了索引如何在不同情况下生效和失效,强调了合理使用索引以优化查询性能的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最左前缀法则(联合索引)

如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效(后面的字段索引失效)。

以 tb_user 表为例,我们先来查看一下之前 tb_user 表所创建的索引。
在这里插入图片描述
在 tb_user 表中,有一个联合索引,这个联合索引涉及到三个字段,顺序分别为:profession,age,status。

对于最左前缀法则指的是,查询时,最左变的列,也就是profession必须存在,否则索引全部失效。而且中间不能跳过某一列,否则该列后面的字段索引将失效。 接下来,我们来演示几组案例,看一下具体的执行计划:

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述
以上的这三组测试中,我们发现只要联合索引最左边的字段 profession存在,索引就会生效,只不过索引的长度不同。 而且由以上三组测试,我们也可以推测出profession字段索引长度为47、age字段索引长度为2、status字段索引长度为5。

explain select * from tb_user where age = 31 and status = '0';

在这里插入图片描述

explain select * from tb_user where status = '0';

在这里插入图片描述
而通过上面的这两组测试,我们也可以看到索引并未生效,原因是因为不满足最左前缀法则,联合索引最左边的列profession不存在。

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

在这里插入图片描述
上述的SQL查询时,存在profession字段,最左边的列是存在的,索引满足最左前缀法则的基本条件。但是查询时,跳过了age这个列,所以后面的列索引是不会使用的,也就是索引部分生效,所以索引的长度就是47。

范围查询

联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效。

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

在这里插入图片描述
当范围查询使用> 或 < 时,走联合索引了,但是索引的长度为49,就说明范围查询右边的status字段是没有走索引的。

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

在这里插入图片描述
当范围查询使用>= 或 <= 时,走联合索引了,但是索引的长度为54,就说明所有的字段都是走索引的。

所以,在业务允许的情况下,尽可能的使用类似于 >= 或 <= 这类的范围查询,而避免使用 > 或 < 。(在oracle中<>是可以走索引的)

索引失效情况

索引列运算(函数运算)

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

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

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

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

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

在这里插入图片描述

字符串不加引号(隐式转换)

字符串类型字段使用时,不加引号,索引将失效。

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;

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

模糊查询

如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。

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模糊查询中,在关键字后面加%,索引可以生效。而如果在关键字前面加了%,索引将会失效。

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连接的条件,左右两侧字段都有索引时,索引才会生效。

数据分布影响

如果MySQL评估使用索引比全表更慢,则不使用索引。

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

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

在这里插入图片描述
经过测试我们发现,相同的SQL语句,只是传入的字段值不同,最终的执行计划也完全不一样,这是为什么呢?

就是因为MySQL在查询时,会评估使用索引的效率与走全表扫描的效率,如果走全表扫描更快,则放弃索引,走全表扫描。 因为索引是用来索引少量数据的,如果通过索引查询返回大批量的数据,则还不如走全表扫描来的快,此时索引就会失效。
(在oracle中全表扫描每次读取时会把附件的几个片缓存,故相同数据量时,全表扫描比走索引反而会更快)

接下来,我们再来看看 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。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值