目录
[使用 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:缺少a和b,c的排序基于a和b相同的前提,单独查c时,c的顺序完全无序;WHERE b=2 AND c=3:缺少a,b和c的组合在无a的情况下是无序的。


