索引失效的情况

本文详细解释了MySQL中的索引失效情况,包括索引在OR条件、LIKE查询、计算操作、最左匹配原则及不同类型条件下的使用,强调了遵守最左匹配原则和正确使用引号的重要性。
摘要由CSDN通过智能技术生成

为了更好的举例,新建一张学生表,并添加id为主键索引,name为普通索引,(name,age)为组合索引

CREATE TABLE `student` (
  `id` int NOT NULL COMMENT 'id',
  `name` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '姓名',
  `age` int DEFAULT NULL COMMENT '年龄',
  `birthday` datetime DEFAULT NULL COMMENT '生日',
  PRIMARY KEY (`id`),
  KEY `idx_name` (`name`) USING BTREE,
  KEY `idx_name_age` (`name`,`age`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

插入数据

INSERT INTO `student` VALUES (1, '张三', 18, '2021-12-23 17:12:44');
INSERT INTO `student` VALUES (2, '李四', 20, '2021-12-22 17:12:48');

1.在where子句中,如果在OR前的条件列是索引列,而在OR后的条件列不是索引列,索引会失效

例:

explain SELECT * FROM `student` where id =1 

在这里插入图片描述
此时命中主键索引,当查询语句带有or后

explain SELECT * FROM `student` where id =1 or birthday = "2021-12-23"

在这里插入图片描述

发现此时type=ALL,全表扫描,未命中索引
总结:查询条件中带有or,除非所有的查询条件都建有索引,否则索引失效
总结:查询条件中带有or,除非所有的查询条件都建有索引,否则索引失效

2. ‘like %xx’ 或 'like %xx%'会造成索引失效

explain select * from student where name = "张三"

在这里插入图片描述

非模糊查询,此时命中name索引,当使用模糊查询后

explain select * from student where name like "%三"

发现此时type=ALL,全表扫描,未命中索引
在这里插入图片描述

3. 在查询条件中对索引列做了计算、函数、类型转换操作,都会导致索引失效

explain select * from student where id-1 = 1

在这里插入图片描述
查询条件为id,但是并没有命中主键索引,因为在索引列上参与了计算
正例

select * from student where id = 2

总结:将参与计算的数值先算好,再查询

4. 违背最左匹配原则

什么是最左匹配原则?
比如,如果创建了一个 (a, b, c) 联合索引,如果查询条件是以下这几种,就可以匹配上联合索引:
where a=1;
where a=1 and b=2 and c=3;
where a=1 and b=2;
需要注意的是,因为有查询优化器,所以 a 字段在 where 子句的顺序并不重要。
但是,如果查询条件是以下这几种,因为不符合最左匹配原则,所以就无法匹配上联合索引,联合索引就会失效:
where b=2;
where c=3;
where b=2 and c=3;
上面这些查询条件之所以会失效,是因为(a, b, c) 联合索引,是先按 a 排序,在 a 相同的情况再按 b 排序,在 b 相同的情况再按 c 排序。所以,b 和 c 是全局无序,局部相对有序的,这样在没有遵循最左匹配原则的情况下,是无法利用到索引的。
值得注意的是,当遇到范围查询(>、<、between、like)就会停止匹配。也就是:

select * from t where a=1 and b>1 and c =1; 

这样a,b可以用到(a,b,c),c索引用不到。
但是如果是建立(a,c,b)联合索引,则a,b,c都可以使用索引,因为优化器会自动改写为最优查询语句。
对于 >=、<=,例如

select * from t_table where a >= 1 and b = 2

a 和 b 字段都用到了联合索引进行索引查询。
对于between,例如

SELECT * FROM t_table WHERE a BETWEEN 2 AND 8 AND b = 2

MySQL 中,BETWEEN 包含了 value1 和 value2 边界值,类似于 >= and =<。而有的数据库则不包含 value1 和 value2 边界值(类似于 > and <)。
这里我们只讨论 MySQL。由于 MySQL 的 BETWEEN 包含 value1 和 value2 边界值,所以这条查询语句 a 和 b 字段都用到了联合索引进行索引查询。

explain select * from student where age = 18

age的索引是和建立再(name,age)组合索引的基础上,当查询条件中没有第一个组合索引的字段(name)会导致索引失效
正例

explain select * from student where age =18 and name ="张三"

在这里插入图片描述
此时才会命中name和(name,age)这个索引

5. 如果列类型是字符串,那在查询条件中需要将数据用引号引用起来,否则不走索引

explain select * from student where name = "张三"

在这里插入图片描述

此时命中name索引,当数据未携带引号后

explain select * from student where name = 2222

在这里插入图片描述

此时未命中name索引,全表扫描

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值