MySQL5.7建⽴全⽂索引(中⽂分词)
MySQL5.7 建⽴全⽂索引
1、ngram and MeCab full-text parser plugins
全⽂检索在MySQL⾥⾯很早就⽀持了,只不过⼀直以来只⽀持英⽂。缘由是他从来都使⽤空格来作为分词的分隔符,⽽对于中⽂来讲,显然⽤空格就不合适,需要针对中⽂语义进⾏分词。但从MySQL 5.7开始,MySQL内置了ngram全⽂检索插件,⽤来⽀持中⽂分词,并且对MyISAM和InnoDB引擎有效。
2、必要的参数设置
在使⽤中⽂检索分词插件ngram之前,先得在MySQL配置⽂件⾥⾯设置他的分词⼤⼩(默认是2),⽐如,
[mysqld]
ngram_token_size=2
分词的SIZE越⼩,索引的体积就越⼤,所以要根据⾃⾝情况来设置合适的⼤⼩。
3、添加全⽂索引
alter⽅式
alter table student add fulltext index full_student(clumn1,clumn2) with parser ngram;
或者
ALTER TABLE `student` ADD FULLTEXT ft_stu_name  (`name`) with parser ngram;
create⽅式
CREATE FULLTEXT INDEX ft_email_name ON `student` (`name`)  with parser ngram;
也可以在创建索引的时候指定索引的长度:
CREATE FULLTEXT INDEX ft_email_name ON `student` (`name`(20)) with parser ngram;
当然也可以在建表时
CREATE TABLE articles (
id INTUNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title,body) WITH PARSER ngram
) ENGINE=InnoDB CHARACTER SET utf8mb4;
4、查询索引
按⾃然语⾔搜索模式查询
SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('关键词' IN NATURAL LANGUAGE MODE);
按布尔全⽂搜索模式查询
2.1 匹配既有管理⼜有数据库的记录
SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('+数据库 +管理' IN BOOLEAN MODE);
2.2匹配有数据库,但是没有管理的记录
SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('+数据库 -管理' IN BOOLEAN MODE);
2.3匹配MySQL,但是把数据库的相关性降低
SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('>数据库 +MySQL' INBOOLEAN MODE);
OK,就不展开讲了,想进⼀步了解,⾃⾏解决。
中⽂分词与全⽂索引
InnoDB默认的全⽂索引parser⾮常合适于Latin,因为Latin是通过空格来分词的。但对于像中⽂,⽇⽂和韩⽂来说,没有这样的分隔符。⼀个词可以由多个字来组成,所以我们需要⽤不同的⽅式来处理。在中我们能使⽤⼀个新的全⽂索引插件来处理它们:.
什么是N-gram?
在全⽂索引中,n-gram就是⼀段⽂字⾥⾯连续的n个字的序列。例如,⽤n-gram来对”信息系统”来进⾏分词,得到的结果如下:
N-gram 例⼦
1N=1 : ‘信’, ‘息’, ‘系’, ‘统’;
2N=2 : ‘信息’, ‘息系’, ‘系统’;
3N=3 : ‘信息系’, ‘息系统’;
4N=4 : ‘信息系统’;
如何在InnoDB中使⽤N-gram Parser?
N-gram parser是默认加载到MySQL中并可以直接使⽤的。我们只需要在DDL中创建全⽂索引时使⽤WITH PARSER ngram。⽐如,下⾯的SQL语句在MySQL 5.7.6及更⾼版本上可以运⾏。
N-gram DDL⽰例
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;
我们引⼊了⼀个新的全局变量叫。由它来决定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_max_token_size将不适⽤于n-gram。
⽆⽤词(stopword)处理:通常,对于⼀个新的词,我们会查表,看是否有匹配的词。如果有,这个词就不会加⼊到全⽂索引中。但是在n-gram中,我们会查stopwords表,看是否包含⾥⾯的词。这样处理的原因是,在中⽇韩的⽂本中,有很多没有意义的字符,词语和标点符号。⽐如,如果我们把‘的’加⼊到stopwords表中,那么对于句⼦‘信息的系统’,在默认情况下我们分词结果为‘信息’,‘系统’。其中‘息的’和‘的系’被过滤掉了。
我们可以通过查询和来查询哪些词在全⽂索引⾥⾯。这是⼀个⾮常有⽤的调试⼯具。如果我们发现⼀个包含某个词的⽂档,没有如我们所期望的那样出现在查询结果中,那么这个词可能是因为某些原因
不在全⽂索引⾥⾯。⽐如,它含有stopword,或者它的⼤⼩⼩于
ngram_token_size等等。这个时候我们就可以通过查询这两个表来确认。下⾯是⼀个简单的例⼦:
简单的调试⽰例
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)
在⾃然语⾔模式(下,⽂本的查询被转换为n-gram分词查询的并集。例如,(‘信息系统’)转换为(‘信息 息系 系统’)。下⾯⼀个例⼦:
⾃然语⾔模式⽰例
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)
在布尔模式(),⽂本查询被转化为n-gram分词的短语查询。例如,(‘信息系统’)转换为(“‘信息 息系 系统’”)。
recursion
布尔模式⽰例
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
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),通配符则被忽略。例如,(‘信息*’)转换为(‘”信息”‘),(‘信息系*’)转换为(‘”信息 息系”‘)。
通配符查询⽰例-2
mysql> SELECT * FROM articles WHERE MATCH (title) AGAINST ('信息*' IN BOOLEAN MODE);
+------------+-----------------+
| FTS_DOC_ID | title          |
+------------+-----------------+
|      1    | 信息系统        |abap多少工资
|      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分词的短语查询。⽐如,(‘信息系统’)转换为(‘”信息 息系 系统”‘)。
短语查询⽰例
elementui 模板mysql> SELECT * FROM articles WHERE MATCH (title) AGAINST('"信息系统"' IN BOOLEAN MODE);
+------------+--------------+
mysql面试题csdn| 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全⽂索引的详细内容,可以参考⽤户⼿册中的部分,还有Jimmy在上的精彩⽂章。如果您想了解更多关于n-gram的详细内容,则可以参考⽤户⼿册中的部分。
web三大组成部分
我们很⾼兴在MySQL 5.7全⽂索引中增强对中⽇韩⽂的⽀持,这也是我们⼯作中很重要的部分,希望这个功能对⼤家有帮助。如果您有任何问题,可以在本blog中进⾏评论,提交⼀个服务需求,或者提交⼀个bug报告。
以上⽤例未做完整验证,仅做参考
测试⽤例:使⽤ "修改密码"关键字的查询的结果
参考
1: blog.csdn/yygg329405/article/details/97110984 2: blog.csdn/qq_33663251/article/details/69612619

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。