MySQL 内置的全文解析器使用单词之间的空格作为分隔符,这对于不使用空格做分隔符的语言是一种限制。为了解决这一限制,MySQL提供了一个支持中文、日文和韩文(CJK)的ngram全文解析器。ngram 全文解析器支持InnoDB和MyISAM的全文索引 。
ngram解析器将文本序列分词为连续的n个字符。例如,你可以使用ngram全文解析器为“abcd”进行不同值的n分词。
n=1: 'a', 'b', 'c', 'd'
n=2: 'ab', 'bc', 'cd'
n=3: 'abc', 'bcd'
n=4: 'abcd'
ngram 全文解析器是一个内置的服务器插件。与其他内置服务器插件一样,它会在服务器启动时自动加载。
ngram_token_size 默认值为2,最小值为1,最大值为10。
例如,ngram_token_size 为2时,ngram解析器将字符串“abc def”解析为四个tokens:“ab”, “bc”, “de” 和 “ef”。
一般建议将ngram_token_size设置为你想要搜索的最大词的大小。如果你只打算搜索单个字符,可以将ngram_token_size设置为1。较小的token大小将产生较小的全文搜索索引,并且搜索速度更快。例如,“Happy Birthday”用简体中文是“生日快乐”,其中“生日”是“birthday”,“快乐”意为“happy”。若要搜索像这样的两个字符的词,可以将ngram_token_size设置为2或更高的值。
ngram_token_size是一个只读变量,只能启动字符串时设置或在配置文件中设置:
启动字符串:
mysqld --ngram_token_size=2
配置文件:
[mysqld]
ngram_token_size=2
以下示例演示了创建一个带有ngram FULLTEXT索引的表,插入样本数据(简体中文文本),并在Information Schema INNODB_FT_INDEX_CACHE表中查看分词后的数据。
mysql> USE test;
mysql> CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body) WITH PARSER ngram
) ENGINE=InnoDB CHARACTER SET utf8mb4;
mysql> SET NAMES utf8mb4;
INSERT INTO articles (title,body) VALUES
('数据库管理','在本教程中我将向你展示如何管理数据库'),
('数据库应用开发','学习开发数据库应用程序');
mysql> SET GLOBAL innodb_ft_aux_table="test/articles";
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE ORDER BY doc_id, position;
要向现有表添加FULLTEXT索引,可以使用ALTER TABLE或CREATE INDEX。例如:
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT
) ENGINE=InnoDB CHARACTER SET utf8mb4;
ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title,body) WITH PARSER ngram;
# Or:
CREATE FULLTEXT INDEX ft_index ON articles (title,body) WITH PARSER ngram;
ngram解析器在解析过程中忽略了单词间的空白,因此“ab cd”和“a bc”都会相应地被解析为"ab", "cd"和"bc"。
与内置全文解析器不同,ngram解析器会排除包含停止词的tokens。默认情况下,ngram解析器采用英语停止词列表,但您可以创建适合中文、日文或韩文的停止词列表。
由于 ngram FULLTEXT
索引仅包含 ngram,并且不包含有关术语开头的信息,因此通配符搜索可能会返回意外结果。以下行为适用于使用 ngram FULLTEXT
搜索索引的通配符搜索:
如果通配符搜索的前缀术语短于 ngram 标记大小,则查询将返回包含以前缀术语开头的 ngram 标记的所有索引行。例如,假设 ngram_token_size=2
,搜索“a*”将返回以“a”开头的所有行。
如果通配符搜索的前缀术语长于 ngram 令牌大小,则前缀术语将转换为 ngram 短语,并忽略通配符运算符。例如,假设 ngram_token_size=2
,“abc*” 通配符搜索转换为 “ab bc”。