【高频面试题】FullText 全文索引(MySQL)

普通索引:匹配完整字段值 ,like '%关键词%' 不走索引,扫描全表;

全文索引 FULLTEXT :专门用来在**长文本(文章、标题、内容)**中搜索单词 / 短语,分词检索,支持语义相关度排序。

1. 基础概念

  • 适用引擎:InnoDB(MySQL5.6 + 支持)、MyISAM
  • 支持字段类型:CHAR、VARCHAR、TEXT
  • 原理:把文本拆分成单词(token),建立单词 → 文档 ID 的倒排索引;搜索时按单词匹配,计算相关性分数。
  • 默认分词规则(英文):按空格、标点分割;中文默认不支持分词,需要插件(ngram 分词器)。

两个重要系统参数

  1. innodb_ft_min_token_size:InnoDB 最小单词长度,默认3。 小于 3 个字符的词不会被收录。
  2. ft_stopword_file:停用词列表(a,the,is,中文的 "的、了"),停用词不会进索引。

⚠️ 中文坑:原生全文索引不切中文词语,连续汉字当成一个字符串。

MySQL 提供 ngram 分词插件,按固定 N 元组切分中文。

2. 创建全文索引

建表时创建

sql 复制代码
CREATE TABLE article (
    id INT PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(200),
    content TEXT,
    FULLTEXT INDEX ft_article(title, content) -- 多字段联合全文索引
) ENGINE=InnoDB;

已有表添加索引

sql 复制代码
ALTER TABLE article ADD FULLTEXT INDEX ft_article(title,content);

删除全文索引

sql 复制代码
ALTER TABLE article DROP INDEX ft_article;

3. 查询语法:MATCH() AGAINST()

语法:

sql 复制代码
MATCH(字段1,字段2) AGAINST ('搜索词' [搜索模式])

MATCH 指定要检索哪些字段,AGAINST 指定搜什么词,以及用哪种搜索规则。

返回值:相关性分数,分数越高代表匹配度越高。

3 种搜索模式

① 自然语言模式(默认 IN NATURAL LANGUAGE MODE)

查找包含关键词的行,按相关性降序;不支持运算符。

sql 复制代码
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

sql 复制代码
SELECT * FROM article
WHERE MATCH(title,content) AGAINST ('+java -spring' IN BOOLEAN MODE);
③ 查询扩展模式 WITH QUERY EXPANSION

先根据关键词找到相关文档,再提取文档里高频词做二次搜索,适合概念扩展,容易引入无关数据。

sql 复制代码
MATCH(title,content) AGAINST ('数据库' WITH QUERY EXPANSION);

4. 中文使用:ngram 分词器

ngram:把中文按 N 个字符滑动切分,ngram_token_size 一般设 2(二元分词)。

建表指定 ngram 解析器

sql 复制代码
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,不能搜单个汉字。

查询示例:

sql 复制代码
SELECT * FROM news WHERE MATCH(content) AGAINST ('深圳' IN NATURAL LANGUAGE MODE);

5. 全文索引优缺点

✅ 优点

  1. 相比 like '%xxx%' 全表扫描,全文索引检索速度快很多;
  2. 自带相关性打分,适合文章搜索场景;
  3. 支持布尔语法、短语匹配。

❌ 缺点

  1. 有最小词长限制,太短的词无法检索;
  2. 高频词(超过半数文档存在)在自然语言模式会被忽略;
  3. 中文原生不支持语义分词,ngram 会产生大量碎词,索引体积大;
  4. DML 开销大:新增 / 修改文本,需要维护倒排索引,写入性能下降;
  5. 不支持部分场景:不能用于ORDER BY以外复杂排序;不适合短字段精确匹配。

6. 什么时候不要用 MySQL FullText?

  • 大量中文搜索、需要分词(人名、专有名词)、高亮、分页权重、同义词 → 推荐 Elasticsearch / Solr
  • 只是简单模糊匹配短字符串 → 普通 B + 树索引 + like 'xxx%'(前缀匹配)

7. 常见踩坑

  1. MATCH 的字段列表,必须和建立全文索引的字段完全一致,否则报错;
  2. 自然语言模式下,如果关键词在超过一半数据里存在,查不出结果;
  3. ngram 分词 token_size 一旦设置,不能在线修改,需要重建索引;
  4. AGAINST里不要直接拼接用户输入,防止注入。
相关推荐
盟接之桥40 分钟前
AI助手:你的7×24小时智能管家——让异常预警无处不在
大数据·网络·数据库·人工智能·制造·ai编程
waoooqwe42 分钟前
问卷样本真实吗
大数据·数据库·算法·数据分析
可乐ea1 小时前
Agent 评测换判据:用终态数据库状态判定任务是否完成
数据库·ui·oracle·mcp工具·agent评测·终态断言·智能体可靠性
l1t1 小时前
DeepSeek总结的一个不含数据的 DuckDB 数据库
服务器·数据库·duckdb
PaperData2 小时前
2007-2020年税收调查面板数据
数据库
程序员清风3 小时前
CSV、Excel 与数据库数据读取实践
数据库·oracle·excel
GEO实战经验分享3 小时前
GEO技术与工具全景:从监测仪表盘到Schema的实战指南
数据库
一个天蝎座的程序猿3 小时前
IoTDB集群扩容:从慌乱到从容的经验分享
数据库
小小龙学IT4 小时前
Python SQLAlchemy 2.0 深度解析:从 Core 到 ORM 的数据访问双引擎
开发语言·数据库·python
DongQiShanRen4 小时前
裁决台账双向互校(上):名册与实物的第一道对账
java·linux·运维·数据库·人工智能·自然语言处理·数据挖掘