mysql原生索引仅支持like 'prefix%'前缀匹配加速,'%suffix'和'%infix%'无法利用b+树索引,必然触发全表扫描;因其依赖字典序定位起点,而通配符前置导致无法剪枝。

直接说结论:MySQL原生索引只能加速 LIKE 'prefix%' 这类前缀匹配;LIKE '%suffix' 或 LIKE '%infix%' 无法用标准B-tree索引,硬查等于默认全表扫描——别指望加个普通索引就能救。
为什么 LIKE 'abc%' 能走索引而 LIKE '%abc' 不能
因为B+树索引按字段完整值排序,LIKE 'abc%' 等价于 name >= 'abc' AND name ,MySQL能快速定位起始页并顺序遍历;但 <code>LIKE '%abc' 没有确定的扫描起点,必须逐行检查每个值是否以 'abc' 结尾,索引完全失效。
实操建议:
- 确保字段上有普通B-tree索引:
CREATE INDEX idx_name ON users(name); - 若字段过长(如
VARCHAR(500)),可用前缀索引节省空间:CREATE INDEX idx_name_prefix ON users(name(20));,但得验证前20位是否足够区分大部分值 - 避免在索引列上套函数:
LOWER(name) LIKE 'abc%'会失效,除非 MySQL 8.0+ 且建了函数索引:CREATE INDEX idx_lower_name ON users((LOWER(name)));
后缀匹配 LIKE '%abc' 的可行解法
核心思路是把“结尾匹配”转成“开头匹配”,靠反向存储 + 前缀索引实现。
实操步骤:
- 添加反向列:
ALTER TABLE users ADD COLUMN name_rev VARCHAR(255) AS (REVERSE(name)) STORED; - 建索引:
CREATE INDEX idx_name_rev ON users(name_rev); - 查询改写:
SELECT * FROM users WHERE name_rev LIKE REVERSE('abc') || '%';(注意:MySQL中用CONCAT()或||开启PADDED模式才安全)
⚠️ 容易踩的坑:反向列必须是 STORED 生成列,VIRTUAL 列无法建索引;REVERSE() 对含多字节字符(如中文、emoji)的字段可能出错,需提前测试。
全模糊 LIKE '%abc%' 不要硬刚索引
标准索引彻底无效,全文索引也不是万能钥匙——它本质是分词检索,不是字符串包含判断。
适用条件与限制:
- 必须用
INNODB引擎且 MySQL ≥ 5.6,创建:ALTER TABLE articles ADD FULLTEXT(title, content); - 中文需 MySQL ≥ 5.7.6 并配置
ngram_token_size=2(默认不搜单字) -
MATCH() AGAINST()不支持通配符组合,AGAINST('abc*')合法,但AGAINST('ab*c')会报错 - 若业务真要字面级包含(比如查日志中的错误码
'ERR-123'),全文索引可能漏匹配,此时应加高选择性前置条件:WHERE status = 'ERROR' AND created_at > '2026-06-01' AND log_text LIKE '%ERR-123%',再配LIMIT 100
大数据量下真正该考虑的路子
当表超百万行、模糊查询高频且不可妥协时,MySQL原生能力已到边界。这时候建再多索引、调再细参数,也比不过一次架构调整。
关键判断点:
- 如果字段是描述、文章、评论等长文本,优先导出到
Elasticsearch或Solr,用专业搜索引擎处理 - 如果只是商品名、用户名等短文本,且数据更新不频繁,可接受定时同步,用
canal+ES是成熟路径 - 如果数据量小(几千~几万)、搜索频次低,全文索引够用;但别忽略
ft_min_word_len和中文分词配置,否则搜'AI'或'云'可能返回空
最常被忽略的一点:模糊查询的性能瓶颈往往不在SQL本身,而在没有前置过滤条件。哪怕加一个 WHERE deleted = 0 或 AND tenant_id = 123,也能让扫描行数从百万级压到几千级——这比所有索引技巧都管用。











