InnoDB全文索引 N gram Parser

2021-07-11 06:28:12 字數 4144 閱讀 3568

innodb預設的全文索引parser非常合適於latin,因為latin是通過空格來分詞的。但對於像中文,日文和韓文來說,沒有這樣的分隔符。乙個詞可以由多個字來組成,所以我們需要用不同的方式來處理。在mysql 5.7.6中我們能使用乙個新的全文索引外掛程式來處理它們:n-gram parser.

什麼是n-gram?

在全文索引中,n-gram就是一段文字裡面連續的n個字的序列。例如,用n-gram來對」資訊系統」來進行分詞,得到的結果如下:

n-gram 例子

12

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示例

12

3

4

5

6

7

8

9

mysql

>

create

table

articles

(fts_doc_id

bigint

unsigned

auto_increment

notnull

primary

key,

title

varchar

(100),

fulltext

index

ngram_idx

(title

)with

parser

ngram

)engine

=innodb

character

set

utf8mb4;

query ok,

0rows

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等等。這個時候我們就可以通過查詢這兩個表來確認。下面是乙個簡單的例子:

簡單的除錯示例

12

3

4

5

6

7

8

9

10

11

12

13

14

15

mysql

>

insert

into

articles

(title

)values

('資訊系統');

query ok,

1row

affected

(0.01

sec)

mysql

>

set

global

innodb_ft_aux_table

="test/articles";

query ok,

0rows

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| +

----

----+--

----

----

----+--

----

-------

+------

-----+

----

----+--

----

----+

3rows

inset

(0.00

sec)

n-gram查詢處理

文字查詢(text searches)

萬用字元查詢(wildcard searches)

短語查詢(phrase searches)

innoDB 全文索引

當b 樹無法滿足索引要求時,比如根據前幾個關鍵字來查詢所有相關資料。innodb 1.2.x版本開始支援全文檢索 全文檢索一般使用倒排索引來實現。倒排索引和b 樹一樣也是一種索引結構,它在輔助表中儲存了單詞與單詞自身在乙個或多個文件中所在位置的對映 1對多 主要有兩種表現形式 比如乙個表t儲存的內容...

mysql 5 7 InnoDB 新增全文索引

首先要確定是mysql 5.6以上 否則不支援 innodb全文索引 fulltext 我使用的環境是mysql5.7 新增步驟如下 修改變數 大部分人都這麼改,看情況吧 新增索引 其他的就是檢視索引情況和驗證索引情況 首先先檢視現在的變數情況 show variables like ft valu...

mysql全文索引的坑 MySQL全文索引問題

我有乙個包含以下資料的 文章 mysql select from articles id title body 1 mysql tutorial dbms stands for database 2 how to use mysql well after you went through a 3 o...