网站首页 > 技术文章 正文
1、最左前缀法则
如果索引了多列(联合索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始, 并且不跳过索引中的列。如果跳跃某一列,索引将会部分失效(后面的字段索引失效)。
以 tb_user 表为例,我们先来查看一下之前 tb_user 表所创建的索引。
通过show index from tb_user;语句我们可以看到tb_user表中有四个索引,一个主键索引,一个唯一索引:user_phone,两个普通索引:user_name,idx_email;
现在我们创建一个组合索引:通过三个字段:profession(专业),age,status
create index user_pro_age_status on tb_user(profession,age,status);
对于最左前缀法则指的是,查询时,最左边列,也就是profession(专业)必须存在,否则索引全部失效。 而且中间不能跳过某一列,否则该列后面的字段索引将失效。 接下来,我们来演示几组案例,看一下 具体的执行计划:
explain select * from tb_user where profession = '软件工程' and age = 31 and status = '0';
从上面的sql语句执行结果截图,我们发现是走了索引的,但是出现了回表查询;应该我们使用的是:select *
explain select * from tb_user where profession = '软件工程' and age = 31;
上面的sql也是走了索引的,因为最左列profession出现在了where后面
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。
思考题:
当执行SQL语句: explain select * from tb_user where age = 31 and status = '0' and profession = '软件工程'; 时,是否满足最左前缀法则,走不走 上述的联合索引,索引长度?
可以看到,是完全满足最左前缀法则的,索引长度54,联合索引是生效的。
注意 : 最左前缀法则中指的最左边的列,是指在查询时,联合索引的最左边的字段(即是 第一个字段)必须存在,与我们编写SQL时,条件编写的先后顺序无关。
2、范围查询
联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效。
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,就说明所有的字段都是走索引 的。
所以,在业务允许的情况下,尽可能的使用类似于 >= 或 <= 这类的范围查询,而避免使用 > 或 < 。
3、索引列运算
不要在索引列上进行运算操作, 否则索引将失效。
在tb_user表中,除了前面介绍的联合索引之外,还有一个索引,是phone字段的单列索引。
//当根据phone字段进行等值匹配查询时, 索引生效。
explain select * from tb_user where phone = '17799990015';
当根据phone字段进行函数运算操作之后,索引失效。
explain select * from tb_user where substring(phone,10,2) = '15';
4、字符串不加引号
字符串类型字段使用时,不加引号,索引将失效。
接下来,我们通过两组示例,来看看对于字符串类型的字段,加单引号与不加单引号的区别:
explain select * from tb_user where phone = '17799990015';
explain select * from tb_user where phone = 17799990015;
经过上面两组示例,我们会明显的发现,如果字符串不加单引号,对于查询结果,没什么影响,但是数 据库存在隐式类型转换,索引将失效。
5、模糊查询
如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。
接下来,我们来看一下这三条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 '%工%';
6、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连接的条件,左右两侧字段都有索引时,索引才会生效。
猜你喜欢
- 2024-10-28 MySQL查询为什么没走索引?这篇文章带你全面解析
- 2024-10-28 什么情况会导致 MySQL 索引失效?(mysql什么情况下会导致索引失效)
- 2024-10-28 用了索引一定就有用吗?如何排查?(使用索引)
- 2024-10-28 MySQL 索引优化分析:为啥你的SQL慢?为啥你建的索引常失效?
- 2024-10-28 MySQL基础(索引分析和使用)(mysql各种索引的使用场景)
- 2024-10-28 MySQL基础(其它SQL优化)(mysql数据库优化及sql调优)
- 2024-10-28 除了网络问题之外,即使对于数据量较小的表
- 2024-10-28 研究了 4.7 个小时终于了解到了索引使用了却没变快的原因
- 2024-10-28 MySQL索引失效带来的性能瓶颈:如何解决这个棘手问题?
- 2024-10-28 常见mysql索引失效条件(常见mysql索引失效条件是什么)
- 1517℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 594℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 521℃MySQL service启动脚本浅析(r12笔记第59天)
- 489℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 489℃启用MySQL查询缓存(mysql8.0查询缓存)
- 477℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 456℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 454℃MySQL server PID file could not be found!失败
- 最近发表
-
- PS所有滤镜的说明(六)(ps滤镜详解)
- 5款小白也能用的在线图片编辑器!电商效率飙升就靠它!
- Java变量(java变量有什么作用)
- Java面试常见问题:Java注解(java中的面试题)
- Java编程入门第一课:HelloWorld(java编程从入门到实践)
- Java基础教程:Java继承概述(java里继承的概述)
- java基础之——访问修饰符(private/default/protected/public)
- 如何规划一个合理的JAVA项目工程结构
- 将机器指令翻译成 JavaScript -- 终极目标
- Web 服务器基准测试:Go vs. Node.js vs. Nim vs. Bun
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)