LIKE以通配符开头时索引完全失效,因B+树无法利用有序性定位,仅'abc%'和'ab_c'可走索引;可用前缀索引、覆盖索引或FULLTEXT索引优化,并避免隐式类型转换。

LIKE 以通配符开头时索引完全失效
当 WHERE name LIKE '%abc' 或 WHERE name LIKE '%abc%' 这类查询出现时,MySQL 无法使用 B+ 树索引的有序性,会直接走全表扫描。这是因为索引是按字典序存储的,而前导通配符让数据库无法确定从哪个叶子节点开始查找。
- 唯一能走索引的
LIKE形式是WHERE col LIKE 'abc%'(前缀匹配),此时可利用索引快速定位到'abc'开头的所有记录 -
WHERE col LIKE 'ab_c'(单字符通配)也能用索引,因为长度固定、前缀明确 - 注意:即使字段有索引,只要左侧带
%,EXPLAIN中的type字段就会显示为ALL
用覆盖索引 + 前缀索引缓解性能问题
如果业务必须支持模糊搜索但又不能全表扫,可以结合字段特性做针对性优化。例如用户昵称搜索,通常只关心前 20 个字符:
ALTER TABLE users ADD INDEX idx_nickname_prefix (nickname(20));
这样 WHERE nickname LIKE '张%' 就能命中该前缀索引,节省空间且提升查询效率。但要注意:
- 前缀长度不能太短(否则区分度低,大量回表),也不能太长(浪费索引空间、降低写入性能)
- 用
SELECT COUNT(DISTINCT LEFT(nickname, 20)) / COUNT(*)估算区分度,理想值 > 0.9 - 覆盖索引对
LIKE 'xxx%'有效,但若查询中包含未建索引的字段(如SELECT id, email FROM users WHERE nickname LIKE '张%'),仍需回表
全文索引替代 LIKE 百分号匹配
对描述类、内容类字段(如文章标题、商品详情),LIKE '%keyword%' 几乎必然慢,应改用 FULLTEXT 索引 + MATCH ... AGAINST:
Yes!Sun基于PHP+MYSQL技术,体积小巧、应用灵活、功能强大,是一款为企业网站量身打造的WEB系统。其创新的设计理念,为企业网的开发设计及使用带来了全新的体验:支持前沿技术:动态缓存、伪静态、静态生成、友好URL、SEO设置等提升网站性能、用户体验、搜索引擎友好度的技术均为Yes!Sun所支持。易于二次开发:采用独创的平台化理念,按需定制项目中的各种元素,如:产品属性、产品相册、新闻列表
ALTER TABLE articles ADD FULLTEXT(title, content);
SELECT * FROM articles WHERE MATCH(title, content) AGAINST('数据库优化' IN NATURAL LANGUAGE MODE);注意点:
- 仅 MyISAM 和 InnoDB 支持,InnoDB 要求 MySQL ≥ 5.6
- 默认忽略少于 4 字符的词(
ft_min_word_len),中文需配合ngram插件或使用第三方方案(如 Elasticsearch) -
AGAINST('xxx*' IN BOOLEAN MODE)支持右截断(类似LIKE 'xxx%'),但不支持左截断
避免隐式类型转换导致索引失效
一个常被忽略的坑:LIKE 字段类型与参数类型不一致时,MySQL 可能自动转换,导致索引失效。例如:
-
phone VARCHAR(20)有索引,但写成WHERE phone LIKE 138%(数字字面量),MySQL 会把phone转成数字比较,索引失效 - 正确写法是
WHERE phone LIKE '138%',确保两边都是字符串 - 同理,
COLLATE不一致(如字段是utf8mb4_0900_as_cs,参数没指定)也可能触发隐式转换
执行前务必用 EXPLAIN 看一眼 key 和 rows,哪怕语句看起来“应该能走索引”。很多慢查就卡在这类细节上。









