MySQL索引失效的情况

目录

对索引使用函数

对索引使用表达式计算

存在索引隐式类型转换

[使用 Like 以通配符开头](#使用 Like 以通配符开头)

联合索引要没有遵循最左前缀法则

[Where 子句中的 OR(索引可能不会完全失效)](#Where 子句中的 OR(索引可能不会完全失效))

最左前缀法则的具体演示

[1. 能命中索引的情况](#1. 能命中索引的情况)

[2. 不能命中索引的情况](#2. 不能命中索引的情况)


对索引使用函数

复制代码
select * from t_user where length(name)=6;

对索引使用表达式计算

复制代码
select * from t_user where id + 1 = 10;

存在索引隐式类型转换

复制代码
select * from t_user where phone = 1300000001;
-- MySQL 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较。
-- 因此相当于  select * from t_user where CAST(phone AS signed int) = 1300000001;

使用 Like 以通配符开头

**LIKE '%xxx'** **LIKE '%xxx%'**通常会导致索引失效(无法使用索引进行快速查找)。

为什么会失效

原因:B+树索引的工作原理

索引好比字典的拼音目录

复制代码
字典结构(按拼音排序):
a-an → 安、按、案...
ang → 昂、肮...
ao → 奥、澳、傲...
ba → 八、巴、拔...

1. 等值查询(高效)

复制代码
WHERE name LIKE '张%'
-- 相当于:找拼音以"zhang"开头的字
-- 直接定位到"zhang"区域,然后顺序扫描 ✅

2. 后缀匹配(失效)

复制代码
WHERE name LIKE '%三'
-- 相当于:找拼音以"san"结尾的字
-- 索引是"an、ang、ao、ba..."的顺序
-- "san"可能出现在任何位置,必须全表扫描 ❌

联合索引要没有遵循最左前缀法则

创建联合索引时,需要注意创建时的顺序,联合索引 (a, b, c) 和 (c, b, a) 在使用的时候会存在差别

比如,如果创建了一个 (a, b, c) 联合索引,如果查询条件是以下这几种,就可以匹配上联合索引

where a=1;

where a=1 and b=2 and c=3;

where b=2 and a=1;

where c=3 and b=2 and a=1;

where a=1 and c = 3;

值得注意的是,字段 a 在where字句的顺序是不重要的

但若查询条件是以下这几种,因为不符合最左匹配原则,所以就无法匹配上联合索引,联合索引就会失效:

where b=2; -- 由于缺少了a字段,索引失效

where c=3; -- 由于缺少了a和b字段,索引失效

where b=2 and c=3; -- 由于缺少了a字段,索引失效

总结一句话:使用联合索引当where条件中缺少了联合索引左侧的列时,索引就会失效

为什么有最左前缀法则

补一张图帮助理解,表示

之所以有最左前缀法则,是因为联合索引的索引树是这样排列的,当缺少了左侧列为查询条件时,右侧字段列无法根据索引树去查找数据,所以索引失效

Where 子句中的 OR(索引可能不会完全失效)

复制代码
select * from t_user where id = 1 or age = 18;

索引为什么可能不会完全失效

最左前缀法则的具体演示

1. 能命中索引的情况

以下查询都包含最左列a,因此能匹配联合索引(MySQL 会自动调整WHERE子句中字段的顺序,不影响匹配):

  • WHERE a=1:只查a,匹配索引最左列;
  • WHERE a=1 AND b=2 AND c=3:匹配a→b→c全部列;
  • WHERE b=2 AND a=1:MySQL 会调整为WHERE a=1 AND b=2,匹配a→b
  • WHERE c=3 AND b=2 AND a=1:调整为WHERE a=1 AND b=2 AND c=3,匹配全部列;
  • WHERE a=1 AND c=3:匹配a列,c能部分利用索引(但b列缺失,c的排序基于a相同、b相同的前提,所以c的查询效率比全匹配低,但仍能用到a的索引)。

2. 不能命中索引的情况

以下查询缺少最左列a,导致联合索引失效(只能全表扫描或走其他索引):

  • WHERE b=2:没有a,无法利用(a,b,c)的有序性(b的排序基于a相同的前提,缺少a时,b的顺序是无序的);
  • WHERE c=3:缺少abc的排序基于ab相同的前提,单独查c时,c的顺序完全无序;
  • WHERE b=2 AND c=3:缺少abc的组合在无a的情况下是无序的。
相关推荐
刀法如飞11 小时前
开箱即用的 DDD(领域驱动设计)工程脚手架,基于 Spring Boot 4.0.1 和 Java 21
java·spring boot·mysql·spring·设计模式·intellij-idea
zbguolei11 小时前
MySQL根据身份证号码计算出生日期和年龄
数据库·mysql
luoluoal14 小时前
基于python大数据的电影市场预测分析(源码+文档)
python·mysql·django·毕业设计·源码
conca14 小时前
Java+MySQL时区难题-Date自动转换String差8小时
数据库·mysql
壹米饭14 小时前
MYSQL进阶:删除视图时视图被lock解决方案
后端·mysql
oMcLin15 小时前
如何在Ubuntu 22.04 LTS上配置并优化MySQL 8.0分区表,提高大规模数据集查询的效率与性能?
android·mysql·ubuntu
一路向北⁢16 小时前
MySQL 5.7 表分区使用说明(视频系统实战)
mysql·分区·分表·表分区
齐鲁大虾17 小时前
SQL Server 和 MySQL的区别
数据库·mysql
东方巴黎~Sunsiny18 小时前
mysql大表空间整理注意点
数据库·mysql
AllData公司负责人19 小时前
AllData数据中台-数据同步平台集成开源项目Seatunnel-Web,完成Mysql到Doris同步流程
数据库·mysql·开源