LIKE '%xxx'一定不走索引,因B+树仅支持左前缀匹配,无法定位结尾匹配的起始位置,优化器直接选择全表扫描。

因为B+树索引只能从左到右匹配前缀,LIKE '%xxx'无法定位起始位置,MySQL直接放弃索引走全表扫描——这不是bug,是索引结构决定的硬限制。
为什么LIKE '%xxx'一定不走索引
B+树叶子节点按字段值字典序严格排序,查找必须能“跳到第一个可能命中项”。LIKE 'xxx%'可以快速定位到'xxx'开头的第一条记录,然后向右顺序遍历;但LIKE '%xxx'要求“结尾为xxx”,而索引里根本没有按结尾排序的结构,所有匹配项散落在不同分支,只能扫完整棵树叶子节点——优化器权衡后认为不如直接全表扫描。
验证方式很简单:EXPLAIN SELECT * FROM users WHERE name LIKE '%明';,只要看到key列为NULL、type为ALL,就确认索引完全没用上。
LIKE写法中哪些能真正触发索引
能否走索引,只看通配符是否出现在左侧不可控位置:
-
LIKE '张%'→ ✅type=range,前缀确定,可定位起点 -
LIKE '张_明'→ ✅ 下划线只占一位,不影响前缀连续性 -
LIKE '%张%'→ ❌ 两端模糊,无起点可言 -
LIKE '张%明'→ ⚠️ 仅'张%'部分参与索引过滤,“%明”不加速
注意:LIKE右边必须是字面量或参数化变量(如?/@kw),不能是表达式(如CONCAT('%', @kw)),否则MySQL无法在优化阶段判定模式是否可索引。
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
中文场景下容易被忽略的字符集陷阱
即使改成LIKE '张%',也可能查不到或不走索引,根源常在字符集和排序规则不一致:
- 表/列用
utf8mb4,但客户端连接用latin1→ 查询时发生隐式转换,索引列被CAST,索引失效 - 排序规则用
utf8mb4_general_ci,遇到“張”和“张”简繁差异时,可能无法命中同一索引分支 - 建表未显式指定
COLLATE,依赖服务器默认值 → 不同环境行为不一致
检查方法:SHOW CREATE TABLE users;确认列定义含CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;再运行SHOW VARIABLES LIKE 'character_set%';和SHOW VARIABLES LIKE 'collation%';,确保client/connection/results三者一致。
真要支持后缀搜索,别硬扛B+树
试图靠REVERSE(name) LIKE REVERSE('xxx') + '%'加函数索引绕过?MySQL 8.0+虽支持函数索引,但REVERSE()会导致索引无法利用原有排序,实际仍是全索引扫描,性能无本质改善。
业务上真需要前后模糊或中缀搜索,该换技术栈就得换:
- 字段内容较长(如商品描述)→ 用
FULLTEXT索引,配合MATCH() AGAINST() - 高并发、复杂相关性排序 → 接入Elasticsearch等专用搜索引擎
- 小数据量且必须用MySQL → 预生成后缀数组并建索引(维护成本高,慎选)
最常被低估的点:不是“有没有索引”,而是“查询能否被转成B+树可加速的区间查找”。LIKE '%xxx'从原理上就不是B+树的设计目标。

















