必须先创建fulltext索引才能使用match() against(),且要求引擎为innodb或myisam、字段为char/varchar/text、字符集支持分词;搜不到词常因停用词、最小词长限制或缓存延迟所致。

MySQL里用MATCH() AGAINST()查关键字,但没建FULLTEXT索引就报错
直接执行MATCH(col) AGAINST('xxx')却提示ERROR 1191: Can't find FULLTEXT index matching the column list,不是SQL写错了,是表压根没配全文索引。InnoDB和MyISAM都支持FULLTEXT,但必须显式创建,且字段类型、字符集有硬性限制。
实操建议:
- 确认存储引擎:用
SHOW CREATE TABLE table_name看引擎是不是InnoDB或MyISAM;非这两者(比如Memory)不支持 - 检查字段类型:只支持
CHAR、VARCHAR、TEXT;INT或BLOB不行 - 字符集需为
utf8mb4或latin1等内置分词支持的编码;utf8mb4_unicode_ci可以,但utf8mb4_bin会导致分词失效 - 建索引语句示例:
ALTER TABLE articles ADD FULLTEXT(title, content)——注意不能跨引擎混用,也不能对单个TEXT字段加普通B-tree索引再指望它支持全文检索
为什么AGAINST('xxx')搜不到明显存在的词?
FULLTEXT默认用自然语言模式(NATURAL LANGUAGE MODE),会过滤停用词、忽略太短/太长的词,并按相关性排序,不是“包含即命中”。比如搜'is'或'the'基本没结果,因为它们在默认停用词表里;搜'a'也失败——InnoDB默认最小词长是3。
实操建议:
- 查当前停用词表:
SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD(InnoDB)或读取配置文件里的ft_stopword_file - 改最小词长需重启MySQL并设
innodb_ft_min_token_size = 2(InnoDB)或ft_min_word_len = 2(MyISAM),改完还得重建全文索引 - 临时绕过停用词和词长限制:用布尔模式
AGAINST('+xxx' IN BOOLEAN MODE),+号强制要求存在,且不走停用词过滤 - 注意布尔模式不自动排序,要相关性得分得手动加
MATCH() AGAINST()作为SELECT字段
LIKE '%xxx%' vs FULLTEXT,什么时候该换?
当数据量上万行后,LIKE '%xxx%'基本等于全表扫描,响应从毫秒变秒级;FULLTEXT底层是倒排索引,查100万行也能保持几十毫秒。但代价是:索引体积大(可能比原表还大)、更新延迟(InnoDB有64MB缓存阈值,超了才刷盘)、不支持正则或模糊匹配(如“相似拼写”)。
实操建议:
- 只对高频搜索的文本字段建FULLTEXT,别给每个
TEXT列都加——索引越多,INSERT/UPDATE越慢 - 如果业务需要前缀匹配(如
WHERE name LIKE 'abc%'),优先用普通B-tree索引,比FULLTEXT更轻量、更准 - 想支持中文?MySQL原生FULLTEXT对中文分词很弱(按字切分),搜“数据库”会被拆成“数”“据”“库”,召回率低;真要中文检索,得接Elasticsearch或用Mroonga插件
- 测试性能差异:用
EXPLAIN SELECT ... MATCH() AGAINST()...看是否用了fulltext类型;EXPLAIN显示type: ALL说明FULLTEXT根本没生效
重建全文索引后搜还是不准,可能是缓存没清
InnoDB会缓存全文索引变更,新插入的数据不会立刻进倒排索引,导致MATCH() AGAINST()查不到刚写入的内容。这不是bug,是设计取舍——为了写入性能牺牲实时性。MyISAM相对实时些,但仍有几秒延迟。
实操建议:
- 强制刷新:执行
OPTIMIZE TABLE table_name(InnoDB),会重建全文索引并清空缓存;但这是锁表操作,线上慎用 - 查当前索引状态:
SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE看最新数据是否已入库;空结果=还没刷进去 - 开发期调试时,可在INSERT后加
SLEEP(1)再查,避免因缓存导致逻辑误判 - 不要依赖FULLTEXT做“强一致”搜索场景,比如用户发完评论立刻搜自己刚写的字——这种需求得配合应用层缓存或双写方案
实际用FULLTEXT最常卡住的点,不是语法写不对,而是建索引时漏了引擎、字符集或字段类型约束;搜不到词时第一反应不该是调SQL,而是先确认停用词表和词长设置。这些细节不报错,但让查询静默失效。










