共计 4737 个字符,预计需要花费 12 分钟才能阅读完成。
这篇文章主要介绍“InnoDB 全文索引是什么”,在日常操作中,相信很多人在 InnoDB 全文索引是什么问题上存在疑惑,丸趣 TV 小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”InnoDB 全文索引是什么”的疑惑有所帮助!接下来,请跟着丸趣 TV 小编一起来学习吧!
InnoDB 全文索引:N-gram Parser
March 26, 2015MySQLShaohua Wang
InnoDB 默认的全文索引 parser 非常合适于 Latin,因为 Latin 是通过空格来分词的。但对于像中文,日文和韩文来说,没有这样的分隔符。一个词可以由多个字来组成,所以我们需要用不同的方式来处理。在 MySQL 5.7.6 中我们能使用一个新的全文索引插件来处理它们:n-gram parser.
什么是 N -gram?
在全文索引中,n-gram 就是一段文字里面连续的 n 个字的序列。例如,用 n -gram 来对”信息系统”来进行分词,得到的结果如下:
N-gram 例子
1
2
3
4
N=1 : 信 , 息 , 系 , 统
N=2 : 信息 , 息系 , 系统
N=3 : 信息系 , 息系统
N=4 : 信息系统
如何在 InnoDB 中使用 N -gram Parser?
N-gram parser 是默认加载到 MySQL 中并可以直接使用的。我们只需要在 DDL 中创建全文索引时使用 WITH PARSER ngram。比如,下面的 SQL 语句在 MySQL 5.7.6 及更高版本上可以运行。
N-gram DDL 示例
1
2
3
4
5
6
7
8
9
mysql CREATE TABLE articles
(
FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(100),
FULLTEXT INDEX ngram_idx(title) WITH PARSER ngram
) Engine=InnoDB CHARACTER SET utf8mb4;
Query OK, 0 rows affected (0.06 sec)
mysql # ALTER TABLE articles ADD FULLTEXT INDEX ngram_idx(title) WITH PARSER ngram;
mysql # CREATE FULLTEXT INDEX ngram_idx ON articles(title) WITH PARSER ngram;
我们引入了一个新的全局变量叫 ngram_token_size。由它来决定 n -gram 中 n 的大小,也就是词的大小。它的默认值是 2,这个时候,我们使用的是 bigram。它的合法的取值范围是 1 到 10。现在,我们很自然会想到一个问题:实际应用中应该如何设置 ngram_token_size 值的大小呢?当然,我们推荐使用 2。但是你也可以通过如下这个简单的规则来可以选择任何合法的值:设置到你希望能查询到的最小的词的大小。如果你想查询到单个字,那么我们需要设置为 1。 ngram_token_size 的值设置的越小,全文索引占用的空间也越小。一般来说,查询正好等于 ngram_token_size 的词,速度会更快,但是查询比它更长的词或短语,则会变慢。
N-gram 分词处理
N-gram parser 和系统默认的全文索引 parser 有如下不同点:
词大小检查:因为有了 ngram_token_size,所以 innodb_ft_min_token_size 和 innodb_ft_max_token_size 将不适用于 n -gram。
无用词(stopword)处理:通常,对于一个新的词,我们会查找 stopwords 表,看是否有匹配的词。如果有,这个词就不会加入到全文索引中。但是在 n -gram 中,我们会查找 stopwords 表,看是否包含里面的词。这样处理的原因是,在中日韩的文本中,有很多没有意义的字符,词语和标点符号。比如,如果我们把‘的’加入到 stopwords 表中,那么对于句子‘信息的系统’,在默认情况下我们分词结果为‘信息’,‘系统’。其中‘息的’和‘的系’被过滤掉了。
我们可以通过查询 INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE 和 INFORMATION_SCHEMA.INNODB_FT_TABLE_TABLE 来查询哪些词在全文索引里面。这是一个非常有用的调试工具。如果我们发现一个包含某个词的文档,没有如我们所期望的那样出现在查询结果中,那么这个词可能是因为某些原因不在全文索引里面。比如,它含有 stopword,或者它的大小小于 ngram_token_size 等等。这个时候我们就可以通过查询这两个表来确认。下面是一个简单的例子:
简单的调试示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql INSERT INTO articles (title) VALUES (信息系统
Query OK, 1 row affected (0.01 sec)
mysql SET GLOBAL innodb_ft_aux_table= test/articles
Query OK, 0 rows affected (0.00 sec)
mysql SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE;
+——–+————–+————-+———–+——–+———-+
| WORD | FIRST_DOC_ID | LAST_DOC_ID | DOC_COUNT | DOC_ID | POSITION |
+——–+————–+————-+———–+——–+———-+
| 信息 | 1 | 1 | 1 | 1 | 0 |
| 息系 | 1 | 1 | 1 | 1 | 3 |
| 系统 | 1 | 1 | 1 | 1 | 6 |
+——–+————–+————-+———–+——–+———-+
3 rows in set (0.00 sec)
N-gram 查询处理
文本查询(Text Searches)
在自然语言模式(NATURAL LANGUAGE MODE)下,文本的查询被转换为 n -gram 分词查询的并集。例如,(‘信息系统’)转换为(‘信息 息系 系统’)。下面一个例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql INSERT INTO articles (title) VALUES (信息系统), (信息 系统), (信息的系统), (信息), (系统), (息系
Query OK, 6 rows affected (0.01 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql SELECT * FROM articles WHERE MATCH (title) AGAINST (信息系统 IN NATURAL LANGUAGE MODE);
+————+—————–+
| FTS_DOC_ID | title |
+————+—————–+
| 1 | 信息系统 |
| 6 | 息系 |
| 2 | 信息 系统 |
| 3 | 信息的系统 |
| 4 | 信息 |
| 5 | 系统 |
+————+—————–+
6 rows in set (0.01 sec)
在布尔模式(BOOLEAN MODE),文本查询被转化为 n -gram 分词的短语查询。例如,(‘信息系统’)转换为(“‘信息 息系 系统”)。
1
2
3
4
5
6
7
mysql SELECT * FROM articles WHERE MATCH(title) AGAINST(信息系统 IN BOOLEAN MODE);
+————+————–+
| FTS_DOC_ID | title |
+————+————–+
| 1 | 信息系统 |
+————+————–+
1 row in set (0.00 sec)
通配符查询(Wildcard Searches)
如果前缀的长度比 ngram_token_size 小,那么查询结果将返回在全文索引中所有以这个词作为前缀的 n -gram 的词。
1
2
3
4
5
6
7
8
9
10
mysql SELECT * FROM articles WHERE MATCH (title) AGAINST (信 * IN BOOLEAN MODE);
+————+—————–+
| FTS_DOC_ID | title |
+————+—————–+
| 1 | 信息系统 |
| 2 | 信息 系统 |
| 3 | 信息的系统 |
| 4 | 信息 |
+————+—————–+
4 rows in set (0.00 sec)
如果前缀的长度大于等于 ngam_token_size,那么这个查询则转换为一个短语(phrase search),通配符则被忽略。例如,(‘信息 *’)转换为 (‘”信息”‘),(‘信息系 *’) 转换为(‘”信息 息系”‘)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mysql SELECT * FROM articles WHERE MATCH (title) AGAINST (信息 * IN BOOLEAN MODE);
+————+—————–+
| FTS_DOC_ID | title |
+————+—————–+
| 1 | 信息系统 |
| 2 | 信息 系统 |
| 3 | 信息的系统 |
| 4 | 信息 |
+————+—————–+
4 rows in set (0.00 sec)
mysql SELECT * FROM articles WHERE MATCH (title) AGAINST (信息系 * IN BOOLEAN MODE);
+————+————–+
| FTS_DOC_ID | title |
+————+————–+
| 1 | 信息系统 |
+————+————–+
1 row in set (0.00 sec)
短语查询(Phrase Searches)
短语查询则被转换为 n -gram 分词的短语查询。比如,(‘信息系统’)转换为(‘”信息 息系 系统”‘)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql SELECT * FROM articles WHERE MATCH (title) AGAINST(信息系统 IN BOOLEAN MODE);
+————+————–+
| FTS_DOC_ID | title |
+————+————–+
| 1 | 信息系统 |
+————+————–+
1 row in set (0.00 sec)
mysql SELECT * FROM articles WHERE MATCH (title) AGAINST (信息 系统 IN BOOLEAN MODE);
+————+—————+
| FTS_DOC_ID | title |
+————+—————+
| 2 | 信息 系统 |
+————+—————+
1 row in set (0.01 sec)
到此,关于“InnoDB 全文索引是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注丸趣 TV 网站,丸趣 TV 小编会继续努力为大家带来更多实用的文章!