在MySQL 5.7.6之前,全文索引只支持英文全文索引,不支持中文全文索引,需要利用分詞器把中文段落預處理拆分成單詞,然後存入數據庫。
從MySQL 5.7.6開始,MySQL內置了ngram全文解析器,用來支持中文、日文、韓文分詞。
ngram全文解析器
MySQL 中使用全局變量ngram_token_size來配置ngram中n的大小,它的取值範圍是1到10,默認值是2。通常ngram_token_size設置爲要查詢的單詞的最小字數。如果需要搜索單字,就要把ngram_token_size設置爲1。在默認值是2的情況下,搜索單字是得不到任何結果的。因爲中文單詞最少是兩個漢字,推薦使用默認值2。
全局變量ngram_token_size的兩種設置方法:
- 啓動mysqld命令時
mysqld --ngram_token_size=2
- 修改MySQL配置文件
[mysqld]
ngram_token_size=2
創建全文索引
- 創建表的時候創建全文索引
CREATE TABLE personal (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
name VARCHAR (20),
undergo TEXT,
FULLTEXT (name, undergo) WITH PARSER ngram
) ENGINE = INNODB;
- 直接通過create index的方式
CREATE FULLTEXT INDEX ft_index ON personal (name,undergo) WITH PARSER ngram;
- 通過 alter table 的方式來添加
ALTER TABLE personal ADD FULLTEXT INDEX ft_index (name,undergo) WITH PARSER ngram;
全文檢索模式
常用的全文檢索模式有兩種:
-
自然語言模式(NATURAL LANGUAGE MODE)
自然語言模式是MySQL 默認的全文檢索模式。自然語言模式不能使用操作符,不能指定關鍵詞必須出現或者必須不能出現等複雜查詢。
-
BOOLEAN模式(BOOLEAN MODE)
BOOLEAN模式可以使用操作符,可以支持指定關鍵詞必須出現或者必須不能出現或者關鍵詞的權重高還是低等複雜查詢。
SELECT * FROM personal
WHERE MATCH (name,undergo)
AGAINST ('張三 PHP' IN NATURAL LANGUAGE MODE);
// 不指定模式,默認使用自然語言模式
SELECT * FROM personal
WHERE MATCH (name,undergo)
AGAINST ('PHP 張三');
在使用過程中如果需要滿足多個檢索字符,可以採用and連接多個MATCH進行查詢。
注意:
使用過程中的50%的門坎限制,當查詢結果很多,幾乎所有記錄都有,或者極少的數據,都有可能會返回非所期望的結果,但是可用IN BOOLEAN MODE即可以避開50%的限制,至於要使用的時候在後面加上即可,例如:
SELECT * FROM 表名稱 WHERE MATCH(字段名1) AGAINST(‘條件字符串1’ IN BOOLEAN MODE)
實例:
如果我要查詢人才簡歷表中的帶有 互聯網、框架 兩個字符的檢索結果,我需要這樣寫,需要注意50%限制的問題,查詢出來的數據更準確:
select * from personal where MATCH('undergo') AGAINST('互聯網*' IN BOOLEAN MODE) and MATCH('undergo') AGAINST('框架*' IN BOOLEAN MODE)
搜索語法規則
+ 一定要有(不含有該關鍵詞的數據條均被忽略)。
- 不可以有(排除指定關鍵詞,含有該關鍵詞的均被忽略)。
> 提高該條匹配數據的權重值。
< 降低該條匹配數據的權重值。
~ 將其相關性由正轉負,表示擁有該字會降低相關性(但不像 - 將之排除),只是排在較後面權重值降低。
* 萬用字,不像其他語法放在前面,這個要接在字符串後面。
" " 用雙引號將一段句子包起來表示要完全相符,不可拆字。
下面的例子演示了BOOLEAN模式下運算符的使用方式:
'互聯網 框架'
無操作符,表示或,要麼包含互聯網,要麼包含框架
'+互聯網 +框架'
必須同時包含兩個詞
'+互聯網 框架'
必須包含互聯網,但是如果也包含框架的話,相關性會更高。
'+互聯網 -框架'
必須包含互聯網,同時不能包含框架。
'+互聯網 ~框架'
必須包含互聯網,但是如果也包含框架的話,相關性要比不包含框架的記錄低。
'+互聯網 +(>框架 <數據庫)'
查詢必須包含互聯網和框架或者互聯網和數據庫的記錄,但是互聯網 框架的相關性要比互聯網 數據庫高。
'互聯網*'
查詢包含以互聯網開頭的單詞的記錄,如互聯網、互聯網公司。
'"some words"'
使用雙引號把要搜素的詞括起來,效果類似於like '%some words%',
例如“some words of wisdom”會被匹配到,而“some noise words”就不會被匹配。
-
只能在類型爲CHAR、VARCHAR或者TEXT的字段上創建全文索引。
-
全文索引只支持InnoDB和MyISAM引擎。
-
MATCH (columnName) AGAINST (‘keywords’)。MATCH()函數使用的字段名,必須要與創建全文索引時指定的字段名一致。如上面的示例,MATCH (title,body)使用的字段名與全文索引ft_articles(title,body)定義的字段名一致。如果要對title或者body字段分別進行查詢,就需要在title和body字段上分別創建新的全文索引。
-
MATCH()函數使用的字段名只能是同一個表的字段,因爲全文索引不能夠跨多個表進行檢索。
-
如果要導入大數據集,使用先導入數據再在表上創建全文索引的方式要比先在表上創建全文索引再導入數據的方式快很多,所以全文索引是很影響TPS的。