InnoDB默認的全文索引parser很是合適於Latin,由於Latin是經過空格來分詞的。但對於像中文,日文和韓文來講,沒有這樣的分隔符。一個詞能夠由多個字來組成,因此咱們須要用不一樣的方式來處理。在MySQL 5.7.6中咱們能使用一個新的全文索引插件來處理它們:n-gram parser.html
什麼是N-gram?mysql
在全文索引中,n-gram就是一段文字裏面連續的n個字的序列。例如,用n-gram來對」信息系統」來進行分詞,獲得的結果以下:sql
N-gram 例子oracle
1工具 2sqlserver 3插件 4調試 |
N=1 : '信', '息', '系', '統';server N=2 : '信息', '息系', '系統';htm 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有以下不一樣點:
咱們能夠經過查詢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)
天然語言模式示例
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) |
布爾模式示例
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)
通配符查詢示例-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) |
通配符查詢示例-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)
短語查詢示例
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!