【MySQL】Mysql索引失效场景(15个必知)(二)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 【MySQL】Mysql索引失效场景(15个必知)(二)

【MySQL】Mysql索引失效场景(15个必知)(一)https://developer.aliyun.com/article/1393376

5、 错误的Like使用

示例:


explain select * from t_user where id_no like '%00%';

explain结果:

image.png

针对like的使用非常频繁,但使用不当往往会导致不走索引。常见的like使用方式有:

  • 方式一:like ‘%abc’;
  • 方式二:like ‘abc%’;
  • 方式三:like ‘%abc%’;

其中方式一和方式三,由于占位符出现在首部,导致无法走索引。这种情况不做索引的原因很容易理解,索引本身就相当于目录,从左到右逐个排序。而条件的左侧使用了占位符,导致无法按照正常的目录进行匹配,导致索引失效就很正常了。 第五种索引失效情况:模糊查询时(like语句),模糊匹配的占位符位于条件的首部。

6、 类型隐式转换

示例:

explain select * from t_user where id_no = 1002;

explain结果:

image.png

id_no字段类型为varchar,但在SQL语句中使用了int类型,导致全表扫描。

出现索引失效的原因是:varchar和int是两个种不同的类型。 解决方案就是将参数1002添加上单引号或双引号。

第六种索引失效情况:参数类型与字段类型不匹配,导致类型发生了隐式转换,索引失效。 这种情况还有一个特例,如果字段类型为int类型,而查询条件添加了单引号或双引号,则Mysql会参数转化为int类型,虽然使用了单引号或双引号:


explain select * from t_user where id = '2';

上述语句是依旧会走索引的。

7、使用OR操作

OR是日常使用最多的操作关键字了,但使用不当,也会导致索引失效。

示例:


explain select * from t_user where id = 2 or username = 'Tom2';

explain结果:

image.png

看到上述执行结果是否是很惊奇啊,明明id字段是有索引的,由于使用or关键字,索引竟然失效了。 其实,换一个角度来想,如果单独使用username字段作为条件很显然是全表扫描,既然已经进行了全表扫描了,前面id的条件再走一次索引反而是浪费了。所以,在使用or关键字时,切记两个条件都要添加索引,否则会导致索引失效。 但如果or两边同时使用“>”和“<”,则索引也会失效:


explain select * from t_user where id  > 1 or id  < 80;

explain结果:

image.png

第七种索引失效情况:查询条件使用or关键字,其中一个字段没有创建索引,则会导致整个查询语句索引失效; or两边为“>”和“<”范围查询时,索引失效。

8、 两列做比较

如果两个列数据都有索引,但在查询条件中对两列数据进行了对比操作,则会导致索引失效。

这里举个不恰当的示例,比如age小于id这样的两列(真实场景可能是两列同维度的数据比较,这里迁就现有表结构):


explain select * from t_user where id > age;

explain结果:

image.png

这里虽然id有索引,age也可以创建索引,但当两列做比较时,索引还是会失效的。

第八种索引失效情况:两列数据做比较,即便两列都创建了索引,索引也会失效。

9、 不等于比较

示例:


explain select * from t_user where id_no <> '1002';

explain结果:

image.png

当查询条件为字符串时,使用”<>“或”!=“作为条件查询,有可能不走索引,但也不全是。


explain select * from t_user where create_time != '2022-02-27 09:56:42';

上述SQL中,由于“2022-02-27 09:56:42”是存储过程在同一秒生成的,大量数据是这个时间。执行之后会发现,当查询结果集占比比较小时,会走索引,占比比较大时不会走索引。此处与结果集与总体的占比有关。

需要注意的是:上述语句如果是id进行不等操作,则正常走索引。


explain select * from t_user where id != 2;

explain结果:

image.png

第九种索引失效情况:查询条件使用不等进行比较时,需要慎重,普通索引会查询结果集占比较大时索引会失效。

10、 is not null

示例:


explain select * from t_user where id_no is not null;

explain结果:

image.png

第十种索引失效情况:查询条件使用is null时正常走索引,使用is not null时,不走索引。

11、 not in和not exists

在日常中使用比较多的范围查询有in、exists、not in、not exists、between and等。


explain select * from t_user where id in (2,3);
explain select * from t_user where id_no in ('1001','1002');
explain select * from t_user u1 where exists (select 1 from t_user u2 where u2.id  = 2 and u2.id = u1.id);
explain select * from t_user where id_no between '1002' and '1003';

上述四种语句执行时都会正常走索引,具体的explain结果就不再展示。主要看不走索引的情况:


explain select * from t_user where id_no not in('1002' , '1003');

explain结果:

image.png

当使用not in时,不走索引?把条件列换成主键试试:


explain select * from t_user where id not in (2,3);

explain结果:

image.png

如果是主键,则正常走索引。

第十一种索引失效情况:查询条件使用not in时,如果是主键则走索引,如果是普通索引,则索引失效。

再来看看not exists:


explain select * from t_user u1 where not exists (select 1 from t_user u2 where u2.id  = 2 and u2.id = u1.id);

explain结果:

image.png

当查询条件使用not exists时,不走索引。

第十二种索引失效情况:查询条件使用not exists时,索引失效。

12、 order by导致索引失效

示例:


explain select * from t_user order by id_no ;

explain结果:

image.png

其实这种情况的索引失效很容易理解,毕竟需要对全表数据进行排序处理。

那么,添加删limit关键字是否就走索引了呢?


explain select * from t_user order by id_no limit 10;

explain结果:

image.png

结果依旧不走索引。在网络上看到有说如果order by条件满足最左匹配则会正常走索引, 在当前8.0.18版本中并未出现。所以,在基于order by和limit进行使用时,要特别留意。是否走索引不仅涉及到数据库版本,还要看Mysql优化器是如何处理的。 这里还有一个特例,就是主键使用order by时,可以正常走索引。


explain select * from t_user order by id desc;

explain结果:

image.png

可以看出针对主键,还是order by可以正常走索引。

另外,笔者测试如下SQL语句:


explain select id from t_user order by age;
explain select id , username from t_user order by age;
explain select id_no from t_user order by id_no;

上述三条SQL语句都是走索引的,也就是说覆盖索引的场景也是可以正常走索引的。

现在将id和id_no组合起来进行order by:


explain select * from t_user order by id,id_no desc;
explain select * from t_user order by id,id_no desc limit 10;
explain select * from t_user order by id_no desc,username desc;

explain结果:

image.png

上述两个SQL语句,都未走索引。

第十三种索引失效情况:当查询条件涉及到order by、limit等条件时,是否走索引情况比较复杂,而且与Mysql版本有关,通常普通索引,如果未使用limit,则不会走索引。order by多个索引字段时,可能不会走索引。其他情况,建议在使用时进行expain验证。

13、 参数不同导致索引失效

此时,如果你还未执行最开始创建的存储过程,建议你先执行一下存储过程,然后执行如下SQL:


explain select * from t_user where create_time > '2023-02-24 09:04:23';

其中,时间是未来的时间,确保能够查到数据。

explain结果:

image.png

可以看到,正常走索引。

随后,我们将查询条件的参数换个日期:


explain select * from t_user where create_time > '2023-11-29 09:04:23';

explain结果:

image.png

此时,进行了全表扫描。这也是最开始提到的奇怪的现象。 为什么同样的查询语句,只是查询的参数值不同,却会出现一个走索引,一个不走索引的情况呢? 答案很简单:上述索引失效是因为DBMS发现全表扫描比走索引效率更高,因此就放弃了走索引。 也就是说,当Mysql发现通过索引扫描的行记录数超过全表的10%-30%时,优化器可能会放弃走索引,自动变成全表扫描。某些场景下即便强制SQL语句走索引,也同样会失效。 类似的问题,在进行范围查询(比如>、< 、>=、<=、in等条件)时往往会出现上述情况,而上面提到的临界值根据场景不同也会有所不同。

第十四种索引失效情况:当查询条件为大于等于、in等范围查询时,根据查询结果占全表数据比例的不同,优化器有可能会放弃索引,进行全表扫描。

14、 其他

当然,还有其他一些是否走索引的规则,这与索引的类型是B-tree索引还是位图索引也有关系,就不再详细展开。

这里要说的其他,可以总结为第十五种索引失效的情况:Mysql优化器的其他优化策略,比如优化器认为在某些情况下,全表扫描比走索引快,则它就会放弃索引。

针对这种情况,一般不用过多理会,当发现问题时再定点排查即可。

小结

本篇文章为大家总结了15个常见的索引失效的场景,由于不同的Mysql版本,索引失效策略也有所不同。大多数索引失效情况都是明确的,有少部分索引失效会因Mysql的版本不同而有所不同。

因此,建议收藏本文,当在实践的过程中进行对照,如果没办法准确把握,则可直接执行explain进行验证

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
14天前
|
缓存 关系型数据库 MySQL
MySQL索引策略与查询性能调优实战
在实际应用中,需要根据具体的业务需求和查询模式,综合运用索引策略和查询性能调优方法,不断地测试和优化,以提高MySQL数据库的查询性能。
|
2月前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
2月前
|
存储 关系型数据库 MySQL
MySQL在企业内部应用场景有哪些
【10月更文挑战第17天】MySQL在企业内部应用场景有哪些
47 0
|
2月前
|
存储 关系型数据库 MySQL
介绍一下MySQL的一些应用场景
【10月更文挑战第17天】介绍一下MySQL的一些应用场景
185 0
|
2月前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
65 3
Mysql(4)—数据库索引
|
28天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第27天】本文深入探讨了MySQL的索引策略和查询性能调优技巧。通过介绍B-Tree索引、哈希索引和全文索引等不同类型,以及如何创建和维护索引,结合实战案例分析查询执行计划,帮助读者掌握提升查询性能的方法。定期优化索引和调整查询语句是提高数据库性能的关键。
155 1
|
2月前
|
存储 关系型数据库 MySQL
如何在MySQL中进行索引的创建和管理?
【10月更文挑战第16天】如何在MySQL中进行索引的创建和管理?
72 1
|
29天前
|
监控 关系型数据库 MySQL
数据库优化:MySQL索引策略与查询性能调优实战
【10月更文挑战第26天】数据库作为现代应用系统的核心组件,其性能优化至关重要。本文主要探讨MySQL的索引策略与查询性能调优。通过合理创建索引(如B-Tree、复合索引)和优化查询语句(如使用EXPLAIN、优化分页查询),可以显著提升数据库的响应速度和稳定性。实践中还需定期审查慢查询日志,持续优化性能。
65 0
|
2月前
|
监控 关系型数据库 MySQL
mysql8索引优化
综上所述,深入理解和有效实施这些索引优化策略,是解锁MySQL 8.0数据库高性能查询的关键。
46 0
|
2月前
|
SQL 关系型数据库 MySQL
美团面试:mysql 索引失效?怎么解决? (重点知识,建议收藏,读10遍+)
本文详细解析了MySQL索引失效的多种场景及解决方法,包括破坏最左匹配原则、索引覆盖原则、前缀匹配原则、`ORDER BY`排序不当、`OR`关键字使用不当、索引列上有计算或函数、使用`NOT IN`和`NOT EXISTS`不当、列的比对等。通过实例演示和`EXPLAIN`命令分析,帮助读者深入理解索引失效的原因,并提供相应的优化建议。文章还推荐了《尼恩Java面试宝典》等资源,助力面试者提升技术水平,顺利通过面试。