一、概念
使用索引是数据库性能优化的必备技能之一。在MySQL数据库中,有四种索引:主键索引、普通索引、唯一索引以及我们这里将要介绍的全文索引(FUNLLTEXT INDEX)。
MySQL全文检索是利用查询关键字和查询列内容之间的相关度进行检索,可以利用全文索引来提高匹配的速度。
全文索引(也称全文检索)是目前搜索引擎使用的一种关键技术。它能够利用【分词技术】等多种算法智能分析出文本文字中关键词的频率和重要性,然后按照一定的算法规则智能地筛选出我们想要的搜索结果。
二、Mysql全文索引版本限制
1. MySQL5.6版本以下,只有MYISAM引擎表支持全文索引;mySQL5.6以上,Innodb引擎表也支持全文索引。
2. 因为Mysql使用空格作为分词的分隔符,所一直以来只支持英文的检索。但从MySQL5.7版本开始,MySQL内置了ngram全文检索插件,用来支持中文分词,并且对MyISAM和InnoDB引擎有效。
三、必要的参数设置
在使用中文检索分词插件ngram之前,先得在MySQL配置文件里面设置他的分词大小(默认是2),比如:
[mysqld]
ngram_token_size=2
分词的size越小,索引的体积越大,所以需要根据自身情况合理设计。(怎么才叫合理?后期实践后再更新。)
四、相关的参数设置
ft_min_word_len = 4
这是全文检索的最小许可字符参数,默认4,通过 SHOW VARIABLES LIKE 'ft_min_word_len' 可查看,中文通常是两个字就是一个词,所以做中文的话需要修改这个值为2最好。
五、设置索引语法(设置数据库字段全文索引)
在MySql中,创建全文索引相对比较简单。例如:我们有一个文章表(articles),其中有主键ID(id)、文章标题(title)、文章内容(content)三个字段。现在我们希望能够在title和content两个列上创建全文索引,article表及全文索引的创建SQL语句根据创建顺序分为两种方式,如下:
1. 建表时就开始建立全文索引:
CREATE TABLE articles (
id INTUNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
content TEXT,
FULLTEXT (title,content) WITH PARSER ngram
) ENGINE=InnoDB CHARACTER SET utf8mb4;
2. 先创建表,再添加完数据后,修改对应字段索引为全文索引
alter table articles add fulltext index testfulltext(title,content) with parser ngram;
注意:如果可能,请尽量先创建表并插入所有数据后再创建全文索引,而不要在创建表时就直接创建全文索引,因为前者比后者的全文索引效率要高。
3. 直接创建索引
CREATE FULLTEXT INDEX index_content ON article(content)
六、全文检索语法
MATCH (col1,col2,...) AGAINST (expr [search_modifier])
使用例子:
SELECT * FROM tab_name WHERE MATCH ('列名1,列名2...列名n') AGAINST('词1 词2 词3 ... 词m');
七、查询方式
查询模式值:
search_modifier: { IN BOOLEAN MODE | IN NATURAL LANGUAGE MODE | WITH QUERY EXPANSION}
1. 自然语言检索:IN NATURAL LANGUAGE MODE
SELECT *,MATCH (title,content) AGAINST ('关键词' IN NATURAL LANGUAGE MODE)
FROM articles WHERE MATCH (title,content) AGAINST ('关键词' IN NATURAL LANGUAGE MODE);
2. 布尔检索:IN BOOLEAN MODE
2.1 概念:剔除一半匹配行以上都有的词。譬如说,每个行都有this这个字的话,那用this去查时,会找不到任何结果,这在记录条数特别多时很有用,原因是数据库认为把所有行都找出来是没有意义的,这时,this几乎被当作是stopword(中断词);但是若只有两行记录时,什么也查不出来的, 因为每个字都出现50%(或以上),要避免这种状况,请用IN BOOLEAN MODE。
2.2 特点
(1)不剔除50%以上符合的row。
(2)不自动以相关性反向排序。
(3)可以对没有FULLTEXT index的字段进行搜寻,但会非常慢。
(4)限制最长与最短的字符串。
(5)套用Stopwords。
2.3 搜索语法规则
(1)+ :一定要有(不含有该关键词的数据条均被忽略)。
(2)- :不可以有(排除指定关键词,含有该关键词的均被忽略)。
(3)> :提高该条匹配数据的权重值。
(4)< :降低该条匹配数据的权重值。
(5)~ :将其相关性由正转负,表示拥有该字会降低相关性(但不像 - 将之排除),只是排在较后面权重值降低。
(6)* :万用字,不像其他语法放在前面,这个要接在字符串后面。
(7)" " :用双引号将一段句子包起来表示要完全相符,不可拆字。
举栗子:
SELECT * FROM articles WHERE MATCH (title,content) AGAINST ('+apple -banana' IN BOOLEAN MODE);
说明:+ 表示AND,即必须包含。- 表示NOT,即必须不包含。即:返回记录必需包含 apple,且不能包含 banner。
SELECT * FROM articles WHERE MATCH (title,content) AGAINST ('apple banana' IN BOOLEAN MODE);
说明:apple和banana之间是空格,空格表示OR。即:返回记录至少包含apple、banana中的一个。
SELECT * FROM articles WHERE MATCH (title,content) AGAINST ('+apple banana' IN BOOLEAN MODE);
说明:返回记录必须包含apple,同时banana可包含也可不包含,若包含的话会获得更高的权重。
SELECT * FROM articles WHERE MATCH (title,content) AGAINST ('+apple ~banana' IN BOOLEAN MODE);
说明: ~ 是我们熟悉的异或运算符。返回记录必须包含apple,若也包含了banana会降低权重。
但是它没有 +apple -banana 严格,因为后者如果包含banana压根就不返回。
SELECT * FROM articles WHERE MATCH (title,content) AGAINST ('+apple +(>banana
3. 查询扩展检索: WITH QUERY EXPANSION
八、注意事项
1、预设搜寻是不分大小写,若要分大小写,columne(字段) 的 character(字符集) 设置要从utf8改成utf8_bin。
2、预设 MATCH...AGAINST 是以相关性排序,由高到低。
3、MATCH(title, content)里的字段必须和FULLTEXT(title, content)里的字段一模一样。如果只要单查title或content一个字段,那得另外再建一个 FULLTEXT(title) 或 FULLTEXT(content),也因为如此,MATCH()的字段一定不能跨table,但是另外两种搜寻方式好像可以。
九、参考文档
1. MySql5.7 InnoDB全文索引(针对中文搜索)
2. MySQL中文全文检索
3. MySQL创建全文索引
4. MySQL 5.7 innodb全文索引
PS:此次经验总结实则当了知识的搬运工,感恩前辈们的付出!