MySQL-創建和使用全文索引(FullText)

MySQL5.6後,除了 MyISAM 存儲引擎,事務型的 Innodb 存儲引擎也支持創建和使用全文索引了。

以下爲測試過程:

--創建測試表

CREATE TABLE article ( 
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY, 
title VARCHAR(200), 
body TEXT
) engine=innodb;


--插入測試值:

insert into article values(null,'MySQL數據庫權威指南','非常不錯的書籍,值得一看');
insert into article values(null,'Oracle數據庫精選','不妨看看');
insert into article values(null,'SQL Servr 數據庫進階','不容錯過');
insert into article values(null,'postgreq 數據庫進階','知道了嗎');


--創建複合鍵title,body全文索引(當然也可以創建單鍵)

create fulltext index ft_idx on article(title,body) with parser ngram;   --使用 ngram 解釋器


--測試是否能走上全文索引的執行計劃

mysql> explain select * from article where match(title,body) against('精 妨');
+----+-------------+---------+------------+----------+---------------+--------+---------+-------+------+----------+-------------------------------+
| id | select_type | table   | partitions | type     | possible_keys | key    | key_len | ref   | rows | filtered | Extra                         |
+----+-------------+---------+------------+----------+---------------+--------+---------+-------+------+----------+-------------------------------+
|  1 | SIMPLE      | article | NULL       | fulltext | ft_idx        | ft_idx | 0       | const |    1 |   100.00 | Using where; Ft_hints: sorted |
+----+-------------+---------+------------+----------+---------------+--------+---------+-------+------+----------+-------------------------------+

以上所示,確認可以走上全文索引


--執行使用全文索引的 SQL,看是否能搜索到相關數據:

mysql> select * from article where match(title,body) against('精 妨');

Empty set (0.00 sec)

如上所示,結果是,搜索不到記錄,怎麼回呢?

往下看:

因爲, mysql 5.7.9 中默認  ngram_token_size 參數的默認值爲2,如下:

mysql> show variables like '%token%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_ft_max_token_size | 84    |
| innodb_ft_min_token_size | 3     |
| ngram_token_size         | 2     |
+--------------------------+-------+

ngram_token_size 參數指的是,以ngram解釋器搜索全文索引時,指定的搜索字符數最小爲2個字符(非字節),但以上SQL

select * from article where match(title,body) against('精 妨');  表示 title like '%精%' and  body like '%妨%' 各只有一個字符,所以搜索不到。(意思是和用like 一樣,但不能以like方式書寫,這樣是走不到全文索引的)。

解決方法:

1、修改 ngram_token_size 參數值:

ngram_token_size是靜態(只讀)參數,必須重啓mysql服務,在啓動mysql時,指定 --ngram_toke_size=1 的方式啓動mysql服務:

[root@dg-st tmp]#mysqld_safe --user=mysql --ngram_token_size=1 &

mysql> show variables like '%token%';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_ft_max_token_size | 84    |
| innodb_ft_min_token_size | 3     |
| ngram_token_size         | 1     |      #參數值已經更改爲1了
+--------------------------+-------+


2、必須要重建全文索引:

create fulltext index ft_idx on article(title,body) with parser ngram;


這時,再執行以上SQL,就可以查到了:

mysql> select * from article where match(title,body) against('精 妨');
+----+-----------------------+--------------+
| id | title                 | body         |
+----+-----------------------+--------------+
|  3 | Oracle數據庫精選      | 不妨看看     |
+----+-----------------------+--------------+
1 row in set (0.01 sec)


另外一種創建全文索引的方式,可以不使用 with ngram 子句,如下:

create fulltext index ft_idx on article(title,body);

這樣創建的全文索引最小和最大搜索字符數(分詞)受 ft_min_word_len  和 ft_max_word_len 參數的影響,這兩個參數也是靜態參數,設置後,也必須要重啓 mysq 服務才能生效,如下:

mysql>show variables like 'ft_%';
+--------------------------+----------------+
| Variable_name            | Value          |
+--------------------------+----------------+
| ft_boolean_syntax        | + -><()~*:""&| |     --該選項用於全文搜索特殊匹配的表達式
| ft_max_word_len          | 84  
          |
| ft_min_word_len          | 4              |
| ft_query_expansion_limit | 20             |
| ft_stopword_file         | (built-in)     |
+--------------------------+----------------+

所以,搜索時,全文索引的各個字段必須最小包含4個字符才能搜索到,如下:

mysql>explain select * from article where match(title,body) against('數據庫精 不妨看看');
+----+-------------+---------+------------+----------+---------------+--------+---------+-------+------+----------+-------------------------------+
| id | select_type | table   | partitions | type     | possible_keys | key    | key_len | ref   | rows | filtered | Extra                         |
+----+-------------+---------+------------+----------+---------------+--------+---------+-------+------+----------+-------------------------------+
|  1 | SIMPLE      | article | NULL       | fulltext | ft_idx        | ft_idx | 0       | const |    1 |   100.00 | Using where; Ft_hints: sorted |
+----+-------------+---------+------------+----------+---------------+--------+---------+-------+------+----------+-------------------------------+
1 row in set, 1 warning (0.00 sec)


mysql> select * from article where match(title,body) against('數據庫精 不妨看看');
+----+-----------------------+--------------+
| id | title                 | body         |
+----+-----------------------+--------------+
|  3 | Oracle數據庫精選      | 不妨看看     |
+----+-----------------------+--------------+


(完)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章