首页 › MySQL › 高级特性(在新窗口打开) › 全文索引
全文索引(Full-Text Index)用于在大量文本数据中进行关键词搜索,比 LIKE '%keyword%' 快得多,且支持自然语言搜索、布尔搜索、相关性排序等能力。
全文索引 vs LIKE
-- LIKE 模糊搜索(无法使用索引,全表扫描)
SELECT * FROM article WHERE body LIKE '%MySQL%';
-- 需要扫描所有行,逐条匹配
-- 全文搜索(使用全文索引)
SELECT * FROM article WHERE MATCH(body) AGAINST('MySQL');
-- 利用全文索引快速定位,而且返回相关性排序创建全文索引
-- 方式一:建表时指定
CREATE TABLE article (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT INDEX ft_body (body) -- 单列全文索引
) ENGINE=InnoDB;
-- 方式二:创建多列全文索引
CREATE TABLE article2 (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT INDEX ft_title_body (title, body) -- 多列
) ENGINE=InnoDB;
-- 方式三:ALTER TABLE 添加
ALTER TABLE article ADD FULLTEXT INDEX ft_body (body);MATCH ... AGAINST 语法
自然语言模式(默认)
-- 按相关性降序返回
SELECT id, title,
MATCH(body) AGAINST('MySQL index') AS relevance
FROM article
WHERE MATCH(body) AGAINST('MySQL index')
ORDER BY relevance DESC;匹配的词条越多,相关性越高。MATCH 中的列必须与索引定义的列完全一致。
布尔模式(BOOLEAN MODE)
支持操作符控制逻辑:
-- + 必须包含,- 必须排除
SELECT * FROM article
WHERE MATCH(body) AGAINST('+MySQL -Oracle' IN BOOLEAN MODE);
-- 包含 MySQL 但不包含 Oracle 的行
-- > 提高权重,< 降低权重
SELECT * FROM article
WHERE MATCH(body) AGAINST('>MySQL <database' IN BOOLEAN MODE);
-- * 通配符(与 LIKE 类似,但效率高)
SELECT * FROM article
WHERE MATCH(body) AGAINST('MySQ*' IN BOOLEAN MODE);
-- 双引号:短语精确匹配
SELECT * FROM article
WHERE MATCH(body) AGAINST('"index strategy"' IN BOOLEAN MODE);
-- () 分组
SELECT * FROM article
WHERE MATCH(body) AGAINST('+(MySQL MariaDB) -Oracle' IN BOOLEAN MODE);全文索引的限制与配置
最短词长限制
MySQL 默认忽略太短的词:
-- InnoDB 全文索引默认最短词长 3 个字符
-- 也就是说 "go"、"in"、"to" 等短词不会被索引,也不会被搜索到
-- 查看/修改 InnoDB 全文索引配置
SHOW VARIABLES LIKE 'innodb_ft_min_token_size'; -- 默认 3
-- 修改需在配置文件中设置
-- [mysqld]
-- innodb_ft_min_token_size = 2 # 支持 2 字符的词MyISAM vs InnoDB 配置差异
| 参数 | 默认值 | 说明 |
|---|---|---|
innodb_ft_min_token_size | 3 | InnoDB 最小词长 |
ft_min_word_len | 4 | MyISAM 最小词长 |
innodb_ft_max_token_size | 84 | InnoDB 最大词长 |
ft_max_word_len | 84 | MyISAM 最大词长 |
修改这些参数后,需要重建全文索引才能生效。
停用词(Stopwords)
MySQL 默认忽略常见停用词("the"、"and"、"a" 等),可通过配置自定义停用词表。
中文全文搜索
MySQL 原生全文索引的分词算法基于空格和标点,对中文(无空格分隔的语言)效果不好。解决方案:
ngram 分词器(MySQL 5.7.6+)
-- 创建全文索引时指定 ngram 解析器
CREATE TABLE article_cn (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT INDEX ft_body (body) WITH PARSER ngram
) ENGINE=InnoDB;-- 配置 ngram 分词长度
-- [mysqld]
-- ngram_token_size = 2 # 2-gram:将"数据库"拆为"数据"、"据库"
-- # 默认 2,1~10 可选ngram 分词器会将中文按 n-gram 切分。例如 ngram_token_size=2 时:
- "MySQL 数据库" → "My"、"yS"、"SQ"、"QL"、"数据"、"据库"
由于 ngram 是字符级别的字节组合,会产生很多无意义的 Token,相关性评分不如专门的搜索引擎。对中文全文搜索要求高的场景,建议使用 Elasticsearch。
全文索引与 EXPLAIN
EXPLAIN SELECT * FROM article
WHERE MATCH(body) AGAINST('MySQL');
-- type: fulltext(表示使用了全文索引)
-- Extra: Using where; Ft_hints: sorted小结
- 全文索引解决
LIKE '%keyword%'的性能问题,适用于文本搜索场景。 MATCH(col) AGAINST('text' [IN BOOLEAN MODE])执行搜索。- 布尔模式支持
+、-、>、<、*、"..."等操作符。 - 全文索引对最短词长(
innodb_ft_min_token_size)和停用词有默认限制。 - 中文全文搜索需用 ngram 分词器,效果有限;复杂搜索场景建议用 Elasticsearch。
上一节:JSON 类型与函数 下一节:字符集与排序规则
