千万级表上LIKE '%关键词%'无法走索引,应按场景选方案:前缀模糊用前缀索引,全模糊用函数索引(如REVERSE),中文全文检索需ngram解析器,务必用EXPLAIN验证执行计划。

直接说结论:千万级表上用 LIKE '%关键词%' 基本等于放弃索引,必须换思路。不是调参或加索引就能救,得按查询模式选对应方案。
LIKE '关键词%' 走前缀索引最轻量
这是唯一能靠原生 B+ 树索引直接加速的模糊场景。只要通配符只在右侧,LIKE 就能走索引扫描而非全表扫描。
- 建索引时长度要合理:
CREATE INDEX idx_name_prefix ON t_users(name(10));太短(如name(2))区分度低,太长(如name(50))浪费空间 - 用
EXPLAIN确认是否命中:type字段必须是range或ref,不能是ALL - 联合索引里,
LIKE字段必须是第一个条件,否则无效;比如(status, name(10))无法支持WHERE name LIKE '张%' - 不支持
ORDER BY name或GROUP BY name—— 前缀索引不保存完整字段值,没法排序
FULLTEXT 索引只对 MATCH() AGAINST() 有效
很多人加了全文索引却还在写 WHERE name LIKE '%张%',结果完全不生效。全文索引不是“给字段加个索引就自动提速”,它是一套独立语法体系。
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
- 字段类型必须是
VARCHAR、TEXT,引擎必须是InnoDB(MySQL 8.0+ 强烈推荐) - 中文需显式指定解析器:
CREATE FULLTEXT INDEX idx_name_ft ON t_users(name) WITH PARSER ngram - 最小词长默认为 4(
innodb_ft_min_token_size=4),搜“李”“AI”会直接被过滤,改配置后必须重建索引 - 停用词(如“的”“了”)默认不索引,查不到别急着删索引,先查
INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD -
AGAINST('张*')只在布尔模式下生效,自然语言模式下星号会被当普通字符忽略
LIKE '%关键词%' 必须反向或函数索引
左模糊和全模糊没有银弹。MySQL 8.0+ 的函数索引是最干净的解法,比手动维护反向字段更可靠。
- 推荐写法:
ALTER TABLE t_users ADD INDEX idx_name_reverse ((REVERSE(name)))(注意双括号,表示函数索引) - 查询改写为:
WHERE REVERSE(name) LIKE REVERSE('%张%'),此时可走索引,EXPLAIN显示type: range - 不要用触发器维护
name_reverse字段——容易漏更新、事务异常时状态不一致,函数索引由 MySQL 自动计算 -
INSTR(name, '张') > 0或LOCATE('张', name) > 0和LIKE '%张%'一样全表扫,执行计划里仍是type: ALL
别忽略业务层拆分与缓存兜底
再好的数据库优化也扛不住无限制的模糊搜索。真实线上系统里,90% 的“优化失败”其实源于没约束输入。
- 前端加限制:禁止用户输少于 2 个字的模糊搜索,或自动补全替代自由输入
- 高频关键词预热:把热搜词结果缓存到 Redis,过期时间设短(如 60s),避免穿透 DB
- 多表 JOIN 模糊条件必须拆:比如
JOIN orders ON u.name LIKE CONCAT('%', o.keyword, '%'),这种写法会让优化器彻底放弃索引,应改为应用层两步查 - 分区表对模糊查询基本无效——B+ 树索引失效时,分区只是把全表扫描变成多个小全表扫描
最容易被忽略的一点:所有方案都依赖数据分布。比如 name 字段大量重复(如“张伟”“张敏”占 30%),即使用了前缀索引或函数索引,实际性能提升也会打折扣。上线前一定要用真实数据集跑 EXPLAIN FORMAT=JSON 看 rows_examined 和 used_columns,而不是只看“是否走索引”。


















