like '%abc'或'%abc%'会导致索引失效,因b+tree要求从最左端匹配;like 'abc%'可走索引,但需字段类型、字符集等严格一致,否则仍全表扫描。

LIKE 用错位置,索引直接失效,JOIN 还没开始就卡在第一张表上。
LIKE '%abc' 会让 JOIN 的驱动表变成全表扫描
当 ON 或 WHERE 中出现 LIKE '%abc',MySQL 无法利用索引定位起始位置,只能对整列逐行匹配。如果这个字段恰好是 JOIN 条件(比如 ON u.name = o.customer_name),而 u.name 上有索引,LIKE '%abc' 也会让该索引完全失效——驱动表 u 就会退化为 type=ALL,哪怕它只有 1 万行,也要扫完全部。
- 常见错误现象:
EXPLAIN显示驱动表的key列为NULL,rows等于表总行数 - WHERE 中写
name LIKE '%john%',即使name有索引,也等价于没索引 - 如果驱动表因 LIKE 变成全表扫描,后续所有被驱动表都会被放大扫描(BNLJ 或更糟)
LIKE 'abc%' 在 JOIN 条件中仍可能触发索引失效
LIKE 'abc%' 理论上能走索引,但前提是字段类型、字符集、表达式都严格匹配。一旦 JOIN 的 ON 子句里存在隐式转换(比如 VARCHAR 字段和 INT 参数比较),或两边字符集不一致(如 utf8mb4 vs utf8),MySQL 会放弃索引走全表扫描——这时 LIKE 'abc%' 形同虚设。
- 检查
EXPLAIN的Extra列是否出现Using where; Using index,没有就说明没走索引 - 用
SHOW CREATE TABLE确认 JOIN 字段的字符集和排序规则是否完全一致 - 避免在 ON 里写函数或表达式,例如
ON UPPER(u.name) = UPPER(o.name),必然索引失效
多个 LIKE 套在子查询或 JOIN 后再过滤,中间结果爆炸
比如先 LEFT JOIN 三张大表,最后才加 WHERE name LIKE '%x%' AND status LIKE '%active%',那前三步已经生成了海量中间结果。尤其 LEFT JOIN 不带强过滤时,左表每行都保留,右表补 NULL,结果集极易膨胀几十倍。
- 实际场景:用户表 10 万行 × 订单表 50 万行 × 商品表 20 万行 → 笛卡尔积风险极高
-
LIKE放在最外层 WHERE,优化器无法下推到 JOIN 前过滤,等于“先拼再筛” - 改法:把高选择性条件(如
status = 'active')提前到 WHERE,并确保它能命中索引;LIKE尽量只用于已大幅缩小的结果集
真正难调的不是单个 LIKE,而是它藏在多层 JOIN 的某个角落,让优化器误判驱动表、放弃索引、启用 BNLJ——等你看到 Using join buffer (Block Nested Loop),往往已经晚了。











