instr不能提升模糊查询性能,与like '%xxx%'同为全表扫描;仅instr(str, substr)=1等价于like 'substr%'可走前缀索引,其余情况均无效。

INSTR 不能让模糊查询变快,它和 LIKE '%xxx%' 一样全表扫描;所谓“高效匹配”是误解,真正提速必须换索引策略或字段设计。
INSTR(str, substr) = 1 等价于 LIKE 'substr%'
这个写法能用,但只对前缀匹配有效,且**仍无法利用普通索引**(除非 MySQL 8.0+ 显式建函数索引)。常见误用是以为 INSTR(name, '张') 比 name LIKE '%张%' 快——实际 EXPLAIN 显示两者都是 type: ALL,扫描行数完全一致。
-
INSTR(name, '张') = 1⇔name LIKE '张%':可命中前缀索引(如果name有索引) -
INSTR(name, '张') > 0⇔name LIKE '%张%':无法走索引,纯计算开销,甚至略慢于 LIKE(多一次函数调用) - MySQL 5.7 及更早版本不支持函数索引,
INSTR调用必然触发全表扫描
LOCATE 和 INSTR 参数顺序不同,选哪个看习惯不是性能
二者底层实现几乎相同,性能无差别。区别仅在参数顺序和可选偏移:
-
INSTR(str, substr):主流编程语言风格(类似 JavaScriptindexOf) -
LOCATE(substr, str[, pos]):Oracle 兼容风格,pos支持从指定位置开始搜索(如日志字段跳过时间戳再查关键词) - 老环境(如 MySQL 5.5)中
LOCATE的三参数形式可能报错,INSTR更稳妥
真正能提升模糊查询性能的替代方案
别在 INSTR 和 LIKE 之间反复横跳,瓶颈不在语法而在执行路径:
- 前缀匹配(
LIKE 'abc%')→ 给字段加普通 B-tree 索引即可生效 - 中/后缀匹配(
LIKE '%abc'或'%abc%')→ 建前缀索引(如INDEX(name(10)))仅对短关键词有效,且需权衡索引大小与覆盖度 - 全文检索需求 → 改用
MATCH ... AGAINST(需FULLTEXT索引),注意中文需配置 ngram 或使用第三方引擎 - 高频固定模式 → 冗余字段 + 触发器维护(如加
is_mobile布尔列判断是否以 1[3-9] 开头) - MySQL 8.0+ → 可建函数索引:
CREATE INDEX idx_name_instr ON t ((INSTR(name, '张'))),但仅当查询条件严格匹配该函数调用时才生效
最容易被忽略的一点:很多声称 “INSTR 比 LIKE 快” 的案例,实际是因为改写后意外避开了隐式类型转换、去掉了 OR 条件、或碰巧让外层 JOIN 提前过滤了数据——不是函数本身快,是整个执行计划变了。验证前先跑 EXPLAIN FORMAT=JSON,盯住 rows_examined 和 key 字段。











