本文来自:http://mysqlserverteam.com/innodb%E5%85%A8%E6%96%87%E7%B4%A2%E5%BC%95%EF%BC%9An-gram-parser/

InnoDB默认的全文索引parser非常合适于Latin,因为Latin是通过空格来分词的。但对于像中文,日文和韩文来说,没有这样的分隔符。一个词可以由多个字来组成,所以我们需要用不同的方式来处理。在MySQL 5.7.6中我们能使用一个新的全文索引插件来处理它们:n-gramparser.

什么是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有如下不同点:

  1. 词大小检查:因为有了ngram_token_size,所以innodb_ft_min_token_sizeinnodb_ft_max_token_size将不适用于n-gram。
  2. 无用词(stopword)处理:通常,对于一个新的词,我们会查找stopwords表,看是否有匹配的词。如果有,这个词就不会加入到全文索引中。但是在n-gram中,我们会查找stopwords表,看是否包含里面的词。这样处理的原因是,在中日韩的文本中,有很多没有意义的字符,词语和标点符号。比如,如果我们把‘的’加入到stopwords表中,那么对于句子‘信息的系统’,在默认情况下我们分词结果为‘信息’,‘系统’。其中‘息的’和‘的系’被过滤掉了。

我们可以通过查询INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHEINFORMATION_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
    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),通配符则被忽略。例如,(‘信息*’)转换为(‘”信息”‘),(‘信息系*’)转换为(‘”信息 息系”‘)。
    通配符查询示例-2
    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全文索引的详细内容,可以参考用户手册中InnoDB全文索引的部分,还有Jimmy在Dr. Dobb上的精彩文章。如果您想了解更多关于n-gram的详细内容,则可以参考用户手册中n-gram parser的部分。

我们很高兴在MySQL 5.7全文索引中增强对中日韩文的支持,这也是我们工作中很重要的部分,希望这个功能对大家有帮助。如果您有任何问题,可以在本blog中进行评论,提交一个服务需求,或者提交一个bug报告

最后,感谢您使用MySQL!

InnoDB全文索引:N-gram Parser【转】的更多相关文章

  1. InnoDB全文索引

    ### 如果想了解全文索引,可以直接将本文复制到mysql的新建查询中,依次执行,即可了解全文索引的相关内容及特性. -- InnoDB全文索引 -- 建表 CREATE TABLE fts_a ( ...

  2. MySQL 5.7 学习:新增配置参数

    背景: 继上次介绍 初识 MySQL 5.6 新功能.参数完之后,刚好MySQL 5.7又GA了,在官方测试里看到,MySQL5.7在功能.性能.可用性.安全和监控上又提升了很高.现在看看和MySQL ...

  3. MySQL 全文检索 ngram Mybatis

    创建全文索引(FullText index) 创建表的同时创建全文索引 FULLTEXT (name) WITH PARSER ngram 通过 alter table 的方式来添加 alter ta ...

  4. MySQL 全文检索 ngram插件

    InnoDB全文索引:N-gram Parser[转] MySql5.7 建立全文索引 InnoDB默认的全文索引parser非常合适于Latin,因为Latin是通过空格来分词的.但对于像中文,日文 ...

  5. MySQL全文索引 FULLTEXT索引和like的区别

    1.概要 InnoDB引擎对FULLTEXT索引的支持是MySQL5.6新引入的特性,之前只有MyISAM引擎支持FULLTEXT索引.对于FULLTEXT索引的内容可以使用MATCH()-AGAIN ...

  6. mysql基础语法之(全文索引)

    1.概要 InnoDB引擎对FULLTEXT索引的支持是MySQL5.6新引入的特性,之前只有MyISAM引擎支持FULLTEXT索引.对于FULLTEXT索引的内容可以使用MATCH()…AGAIN ...

  7. InnoDB FULLTEXT

    1.概要 InnoDB引擎对FULLTEXT索引的支持是MySQL5.6新引入的特性,之前只有MyISAM引擎支持FULLTEXT索引.对于FULLTEXT索引的内容可以使用MATCH()…AGAIN ...

  8. InnoDB INFORMATION_SCHEMA FULLTEXT Index Tables

    InnoDB INFORMATION_SCHEMA FULLTEXT Index Tables 下表提供了FULLTEXT索引的元数据: mysql> SHOW TABLES FROM INFO ...

  9. [MySQL Reference Manual] 8 优化

    8.优化 8.优化 8.1 优化概述 8.2 优化SQL语句 8.2.1 优化SELECT语句 8.2.1.1 SELECT语句的速度 8.2.1.2 WHERE子句优化 8.2.1.3 Range优 ...

随机推荐

  1. URLDecoder解析url编码

    try { strJson = URLDecoder.decode(strJson, "utf-8"); } catch (UnsupportedEncodingException ...

  2. 使用Extjs组件实现Top-Left-Main布局并且增加事件响应

    每次在毕业答辩会上,看到同专业的同学只要是XXX管理系统,就是下图所示的界面,看来这中布局还是很受欢迎的(偷笑).接下来进入我们正题,在web项目无论是前端还是后台管理比较常见的布局就是Top-Lef ...

  3. jQuery笔记总结

    来源于:http://blog.poetries.top/2016/10/20/review-jQuery/ http://www.jianshu.com/p/f8e3936b34c9 首先,来了解一 ...

  4. jQuery链式操作[转]

    用过jQuery的朋友都知道他强大的链式操作,方便,简洁,易于理解,如下 $("has_children").click(function(){ $(this).addClass( ...

  5. Angular 2 - 5 分钟快速入门

    原文地址: https://angular.io/docs/ts/latest/quickstart.html 让我们从 0 开始创建一个简单的 Angular 2 应用. 下载任何版本的 angul ...

  6. poi导出的excel的数字小数位过多?

    最近在使用Apache的POI组件对Excel进行操作,在对excel导出的时候,导出的数字本来只有两位小数,得到的结果就变成了很多位小数.如下面的图所示: 虽然对单元格使用了setCellStyle ...

  7. python对Mysql操作和使用ORM框架(SQLAlchemy)

    python对mysql的操作 Mysql 常见操作 数据库操作 创建数据库 create database fuzjtest 删除数据库 drop database fuzjtest 查询数据库 s ...

  8. 【Linux】使用update-alternatives命令进行版本的切换

    引言 在Redhat中也有此功能,用于切换不同版本. 在Debian系统中,我们可能会同时安装有很多功能类似的程序和可选配置,可能会出现同一软件的多个版本并存的场景.比如像是一些编程语言工具,一些系统 ...

  9. sql中的inner join ,left join ,right join

    左连接LEFT JOIN, 也就是说,左外连接的含义是限制连接关键字右端的表中的数据必须满足连接条件,而不关左端的表中的数据是否满足连接条件,均输出左端表中的内容.不满足连接条件的 ,连接字段栏位将对 ...

  10. centos ab命令安装

    yum install apr-util -ymkdir abcd abyum -y install yum-utils -yyumdownloader httpd yum localinstall ...