在MySQL 5.7.6之前,全文索引只支持英文全文索引,不支持中文全文索引,需要利用分詞器把中文段落預處理拆分成單詞,然後存入數據庫。
從MySQL 5.7.6開始,MySQL內置了ngram全文解析器,用來支持中文、日文、韓文分詞。
本文使用的MySQL 版本是5.7.22,InnoDB數據庫引擎。
mysql原生全文解析器(ngram)
MySQL 中使用全局變量ngram_token_size來配置ngram中n的大小,它的取值範圍是1到10,默認值是2。通常ngram_token_size設置爲要查詢的單詞的最小字數。如果需要搜索單字,就要把ngram_token_size設置爲1。在默認值是2的情況下,搜索單字是得不到任何結果的。因爲中文單詞最少是兩個漢字,推薦使用默認值2。
全局變量ngram_token_size的兩種設置方法:
1、啓動mysqld命令時
mysqld --ngram_token_size=2
2、修改MySQL配置文件
[mysqld]
ngram_token_size=2
創建全文索引
1、創建表的同時創建全文索引
CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR (200),
body TEXT,
FULLTEXT (title, body)
) ENGINE = INNODB;
2、通過 alter table 的方式來添加
ALTER TABLE articles ADD FULLTEXT INDEX ft_index (title,body) ;
假如數據庫有如下數據:
查詢方法:select * from articles where MATCH (title,body) AGAINST ('布衣');
mysql全文檢索模式:
常用的全文檢索模式有兩種:
1、自然語言模式(NATURAL LANGUAGE MODE) ,自然語言模式是MySQL 默認的全文檢索模式。自然語言模式不能使用操作符,不能指定關鍵詞必須出現或者必須不能出現等複雜查詢。
2、BOOLEAN模式(BOOLEAN MODE),BOOLEAN模式可以使用操作符,可以支持指定關鍵詞必須出現或者必須不能出現或者關鍵詞的權重高還是低等複雜查詢。
MySQL中文全文索引查詢:
select * from articles where MATCH (title,body) AGAINST ('布衣');
MySQL中文全文索引查詢,根據匹配度權重來排序
select *,match(title,body) AGAINST ('{$search}') as score from articles order by score desc
mysql全文搜索語法(BOOLEAN MODE):
SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('+先帝 -出師表' IN BOOLEAN MODE);
解析:+ 表示AND,即必須包含。- 表示NOT,即不包含。
SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('先帝 諸葛亮' IN BOOLEAN MODE);
解析:先帝和諸葛亮之間是空格,空格表示OR,即至少包含先帝、諸葛亮中的一個即可。
SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('+先帝 賞罰' IN BOOLEAN MODE);
解析:必須包含“先帝 ”,但是如果同時也包含“ 賞罰 ”則會獲得更高的權重。
SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('+先帝 ~布衣' IN BOOLEAN MODE);
解析:~ 是我們異或運算符。返回的記錄必須包含先帝,但是如果同時也包含“ 布衣 ”會降低權重。但是它沒有 +先帝 -布衣嚴格,因爲後者如果包含‘’布衣‘’壓根就不返回。
mysql全文搜索注意事項:
- 只能在類型爲CHAR、VARCHAR或者TEXT的字段上創建全文索引。
- 全文索引只支持InnoDB和MyISAM引擎。
- MATCH (columnName) AGAINST ('keywords')。MATCH()函數使用的字段名,必須要與創建全文索引時指定的字段名一致。如上面的示例,MATCH (title,body)使用的字段名與全文索引ft_articles(title,body)定義的字段名一致。如果要對title或者body字段分別進行查詢,就需要在title和body字段上分別創建新的全文索引。
- MATCH()函數使用的字段名只能是同一個表的字段,因爲全文索引不能夠跨多個表進行檢索。
- 如果要導入大數據集,使用先導入數據再在表上創建全文索引的方式要比先在表上創建全文索引再導入數據的方式快很多,所以全文索引是很影響TPS的。
參考文章:
https://www.jianshu.com/p/c48106149b6a