普通索引:匹配完整字段值,
like '%关键词%'不走索引,扫描全表;全文索引 FULLTEXT:专门用来在长文本(文章、标题、内容)中搜索单词 / 短语,分词检索,支持语义相关度排序。
1. 基础概念
- 适用引擎:
InnoDB(MySQL5.6 + 支持)、MyISAM - 支持字段类型:
CHAR、VARCHAR、TEXT - 原理:把文本拆分成单词(token),建立单词 → 文档 ID 的倒排索引;搜索时按单词匹配,计算相关性分数。
- 默认分词规则(英文):按空格、标点分割;中文默认不支持分词,需要插件(ngram 分词器)。
两个重要系统参数
innodb_ft_min_token_size:InnoDB 最小单词长度,默认3。 小于 3 个字符的词不会被收录。ft_stopword_file:停用词列表(a,the,is,中文的 “的、了”),停用词不会进索引。
⚠️ 中文坑:原生全文索引不切中文词语,连续汉字当成一个字符串。
MySQL 提供
ngram分词插件,按固定 N 元组切分中文。
2. 创建全文索引
建表时创建
CREATE TABLE article ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(200), content TEXT, FULLTEXT INDEX ft_article(title, content) -- 多字段联合全文索引 ) ENGINE=InnoDB;已有表添加索引
ALTER TABLE article ADD FULLTEXT INDEX ft_article(title,content);删除全文索引
ALTER TABLE article DROP INDEX ft_article;3. 查询语法:MATCH() AGAINST()
语法:
MATCH(字段1,字段2) AGAINST ('搜索词' [搜索模式])MATCH 指定要检索哪些字段,AGAINST 指定搜什么词,以及用哪种搜索规则。
返回值:相关性分数,分数越高代表匹配度越高。
3 种搜索模式
① 自然语言模式(默认IN NATURAL LANGUAGE MODE)
查找包含关键词的行,按相关性降序;不支持运算符。
SELECT id,title, MATCH(title,content) AGAINST ('java' IN NATURAL LANGUAGE MODE) AS score FROM article WHERE MATCH(title,content) AGAINST ('java');规则:
- 词出现频率太高(超过 50% 文档)会被当成停用词,搜不到!
- 最小词长限制生效。
② 布尔模式IN BOOLEAN MODE
支持+ - > < * "短语"运算符,不计算相关性排序,只判定是否匹配。
| 符号 | 含义 |
|---|---|
+java | 必须包含 java |
-mysql | 不能包含 mysql |
java* | 前缀匹配,java 开头单词 (java,javac) |
"hello world" | 精确短语,连续完整词组 |
>word | 提高该词相关性 |
<word | 降低该词相关性 |
示例:必须有 java,不能有 spring
SELECT * FROM article WHERE MATCH(title,content) AGAINST ('+java -spring' IN BOOLEAN MODE);③ 查询扩展模式WITH QUERY EXPANSION
先根据关键词找到相关文档,再提取文档里高频词做二次搜索,适合概念扩展,容易引入无关数据。
MATCH(title,content) AGAINST ('数据库' WITH QUERY EXPANSION);4. 中文使用:ngram 分词器
ngram:把中文按 N 个字符滑动切分,ngram_token_size一般设 2(二元分词)。
建表指定 ngram 解析器
CREATE TABLE news( id INT PRIMARY KEY AUTO_INCREMENT, content TEXT, FULLTEXT INDEX ft_news(content) WITH PARSER ngram ) ENGINE=InnoDB;注意:
ngram_token_size=2,最小搜索长度是 2,不能搜单个汉字。
查询示例:
SELECT * FROM news WHERE MATCH(content) AGAINST ('深圳' IN NATURAL LANGUAGE MODE);5. 全文索引优缺点
✅ 优点
- 相比
like '%xxx%'全表扫描,全文索引检索速度快很多; - 自带相关性打分,适合文章搜索场景;
- 支持布尔语法、短语匹配。
❌ 缺点
- 有最小词长限制,太短的词无法检索;
- 高频词(超过半数文档存在)在自然语言模式会被忽略;
- 中文原生不支持语义分词,ngram 会产生大量碎词,索引体积大;
- DML 开销大:新增 / 修改文本,需要维护倒排索引,写入性能下降;
- 不支持部分场景:不能用于
ORDER BY以外复杂排序;不适合短字段精确匹配。
6. 什么时候不要用 MySQL FullText?
- 大量中文搜索、需要分词(人名、专有名词)、高亮、分页权重、同义词 → 推荐 Elasticsearch / Solr
- 只是简单模糊匹配短字符串 → 普通 B + 树索引 +
like 'xxx%'(前缀匹配)
7. 常见踩坑
MATCH的字段列表,必须和建立全文索引的字段完全一致,否则报错;- 自然语言模式下,如果关键词在超过一半数据里存在,查不出结果;
- ngram 分词 token_size 一旦设置,不能在线修改,需要重建索引;
AGAINST里不要直接拼接用户输入,防止注入。