右模糊('abc%')能走b+树索引,因为b+树按字典序有序存储,mysql可依前缀快速定位起始点并range扫描;而'%abc'和'%abc%'无确定起点,只能全表扫描。

右模糊('abc%')为什么能走B+树索引
因为B+树索引是按字典序有序存储的,MySQL可以利用前缀确定性快速定位起始位置,再向右连续扫描符合条件的叶子节点——这本质就是range扫描,和WHERE name >= 'abc' AND name 逻辑等价。
LEFT LIKE '%abc' 为何必然全表扫描
左模糊破坏了“有序起点”,B+树无法知道从哪一页开始查。比如name LIKE '%三',所有以“张三”“李三”“王三”结尾的记录散落在树的不同分支,只能逐页读取全部叶子节点判断。
-
EXPLAIN里type = ALL或key = NULL就是明确信号 - 哪怕字段有索引、数据量小,只要模式以
%开头,优化器就放弃索引 - 注意:
_(下划线)单字符匹配不影响前缀固定性,name LIKE '张_'仍可走索引
函数包装会让'abc%'也失效
看似写了右模糊,但一加函数就前功尽弃。索引存的是原始值,不是计算结果。
- ❌
WHERE UPPER(name) LIKE 'ZHANG%':索引失效 - ❌
WHERE TRIM(name) LIKE '张%':索引失效 - ❌
WHERE IFNULL(name, '') LIKE '张%':索引失效 - ✅ 正确做法:确保字段本身无空格、非空;或用生成列+索引(MySQL 5.7+)
覆盖索引对LIKE查询的缓解有限
覆盖索引能避免回表,但不能解决左/全模糊的根本问题。它只对已走索引的查询(如name LIKE '张%')有效。
- 如果
SELECT *+name LIKE '%张%',即使name有索引,key仍是NULL - 覆盖索引要求
SELECT字段和WHERE条件字段都在同一索引中,但左模糊连索引都进不去 - 真正高频任意位置匹配,别硬扛,该上
FULLTEXT或Elasticsearch就得上
EXPLAIN没看,等于没验证;而函数包装、隐式类型转换这些“看起来没问题”的写法,恰恰是最隐蔽的索引杀手。











