like '%abc'完全不走索引,因为b+树按字典序从左到右排序,而'%abc'需匹配结尾为abc的字符串,其在索引中位置分散,无法利用树结构快速定位,只能全表扫描。

LIKE '%abc' 为什么完全不走索引
因为 B+ 树索引是按字符串**字典序从左到右排序**的,而 LIKE '%abc' 要求匹配“以 abc 结尾”的任意字符串——比如 'xabc'、'helloabc'、'abc',它们在索引树里根本不在相邻位置,甚至可能散落在不同层级。MySQL 没法从树根开始“跳”到某个起点再往下找,只能放弃索引,直接全表扫描。
用 EXPLAIN 看一眼就明白失效表现
执行
EXPLAIN SELECT * FROM user WHERE name LIKE '%lin';,如果
name 有索引,你会看到:•
type 字段是 ALL(全表扫描)或 index(全索引扫描)•
key 字段为 NULL•
rows 值接近表总行数这三点加起来,就是索引彻底没被用上的铁证。
真想查后缀或包含?别硬扛 LIKE
强行优化 LIKE '%abc' 效果有限,不如换思路:
- 改用
FULLTEXT索引 +MATCH ... AGAINST:适合自然语言检索,但要求字段类型为CHAR/VARCHAR/TEXT,且最小词长默认 4(需调ft_min_word_len) - 建反向索引:对字段做
REVERSE(name),再在结果上建普通索引,查后缀就变成前缀查询 ——SELECT * FROM user WHERE REVERSE(name) LIKE 'cba%';
- 覆盖索引 + 回表(仅限小数据量):先只查主键,再 JOIN 回原表,减少 IO:
SELECT u.* FROM (SELECT id FROM user WHERE name LIKE '%lin') t JOIN user u ON u.id = t.id;
,内层能走Using index,但整体仍比不上前两种方案稳定
最容易被忽略的坑:你以为走了索引,其实只是“扫了索引”
有人看到 EXPLAIN 里 type = index 就以为“用了索引”,其实这是**全索引扫描**(遍历整个二级索引 B+ 树叶子节点),和全表扫描性能差别不大,尤其当索引字段较宽、回表代价高时,反而更慢。真正有效的索引使用,必须是 type = range 或更好(ref/const),且 key 明确显示索引名。











