基于MySQL的中文全文搜索研究
2017-12-15吴东明王丽娟
吴东明+王丽娟
摘要:随着网络数据库应用的发展,用户对数据查询速度的要求也越来越高了,为了从海量文字信息中快速找到所需的相关信息,很多应用系统都通过全文检索技术来提高系统的检索效率。MySQL5.7.6之后内置了n-gram parser全文检索插件,用来支持中文分词,实现中文全文检索,能够支持百万级数据的检索。该文将针对全文索引创建的注意事项、中文全文检索的特点和应用进行简单的介绍。
关键词:n-gram parser;FULLTEXT INDEX;全文检索
中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2017)32-0007-02
全文搜索通常用于基于WEB的应用程序(用来搜索网站、产品目录、新闻和其他数据)、文档管理系统以及自定义应用程序,以便于对存储在MySQL数据库中的数据提供文本搜索功能。MySQL支持对表中基于纯字符的数据执行全文查询,全文查询可以包括词和短语,或者词或短语的多种形式。
全文搜索可以对数据库中文本数据的查询创建全文索引,从而提高查询效率。MySQL在高并发连接、数据库记录数较多的情况下,对数百万行文本执行like查询的全文搜索方式效率差,因为以通配符%开头查询的时候是不能利用索引的,需要从第一条记录遍历至最后一条记录,对数据库的压力很大,可能会导致数据库崩溃。但对于同样的数据,全文搜索只需要几秒或更少的时间。并且与仅适用于字符模式的like谓词不同,全文搜索可以根据特定语言的规则和短语进行操作,针对数据执行语言搜索,从而提高了性能和效率。
MySQL全文索引是专门为了解决模糊查询提供的,在很早的版本就已经支持全文检索了,只是只支持英文的全文检索,从MySQL 5.7.6之后内置了n-gram parser全文检索插件,用来支持中文分词,并且对MyISAM和InnoDB引擎都有效,在全文索引中,n-gram就是一段文字里面连续的n个字的序列。
1 设置必要的参数
在使用中文检索分词插件n-gram之前,可以在mysql的配置文件my.cnf(linux操作系统)或my.ini(windows操作系统)中设置分词的大小。
[mysqld]
ngram_token_size=2
设置完成后,需要重启MySQL服务。ngram_token_size=2是将分词大小设置为2,分词的值越大,索引的体积就越大,所以要根据具体数据库的情况来设置合适的分词大小。全局变量默认为2,可以在1到10之间。对于分词大小的检查,因为有了ngram_token_size,所以,innodb_ft_min_token_size和innodb_ft_max_token_size将不适用于n-gram。
2 创建全文索引
N-gram parser是默认加载到MySQL中并可以直接使用的,只需要在DDL(数据定义语言)中创建全文索引时使用WITH PARSER ngram,n-gram parser在MYSQL5.7.6及更高的版本可以运行。
2.1 在创建表的时候添加全文索引
CREATE TABLE bookinfo(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
bookname VARCHAR(50),
content TEXT,
FULLTEXT(bookname,content) WITH PARSER ngram);
2.2 使用ALTER TABLE语句在已经存在的表上创建全文索引
在修改表的时候添加全文索引
ALTER TABLE bookinfo ADD FULLTEXT INDEX ft_booknamecontent (bookname,content) WITH PARSER ngram;
2.3 使用CREATE FULLTEXT INDEX语句在已经创建的表上创建全文索引
CREATE FULLTEXT INDEX ft_booknamecontent ON bookinfo(bookname,content) WITH PARSER ngram;
3 检索方式
全文检索语法:
MATCH (column1,column2,...) AGAINST (要查找的内容 [search_modifier])
search_modifier: { IN BOOLEAN MODE | WITH QUERY EXPANSION }
MATCH:创建全文索引的列(必须是char、varchar或text数据类型)。
AGAINST:要查找的内容。
search_modifier:语言的检索模式,包括以下三种:
3.1 自然语言检索模式(NATURAL LANGUAGE MODE)
MySQL全文检索的默认模式,即IN NATURAL LANGUAGE MODE可以省略不写。自然语言搜索模式的特点:
(1) 忽略停词(stopword),停词类似于SQL Server全文检索中的“干扰词”或“终止词”,用于在分词时忽略常见的不重要的词,用来去掉那些经常出现但对搜索没有帮助的词,所以搜索这些不会获得任何结果。
(2) 剔除一半记录以上都有的词,如果某个词在数据集中频繁出现的几率超过了50%,也会被认为是停词。
(3) 搜索结果都是具有相关性的数据,返回结果自动按相关性由高到低排序。
例:使用中文全文檢索查询出bookinfo表中包含事务或全文检索的书籍信息。endprint
SELECT * FROM bookinfo WHERE MATCH(bookname,content) AGAINST('事务 全文检索');
其中空格表示or,即检索的行只要包含“事务”和“全文检索”两个关键词之一就被显示结果。
或者:
SELECT * FROM bookinfo WHERE MATCH(bookname,content) AGAINST('事务 全文检索' IN NATURAL LANGUAGE MODE);
3.2 布尔检索模式(BOOLEAN MODE)
布尔查找模式没有自然语言搜索模式中的50%的规则,即便有词语在数据集中频繁出现的几率超过了50%,也会被作为搜索目标进行检索并返回结果,而且检索时单词的局部匹配也会被作为目标进行检索。
查询的结果是不会自动以相关性进行排序,可以对没有设置为全文索引的字段进行搜索,但是速度会非常慢。
布尔全文检索支持的操作符:
(1) “+”:必须包含指定的关键词,不包含该关键词的记录均被忽略。
SELECT * FROM bookinfo WHERE MATCH(bookname,content) AGAINST('事务 +全文检索' IN BOOLEAN MODE);
检索出的记录必须包含“全文检索”关键词。
SELECT * FROM bookinfo WHERE MATCH(bookname,content) AGAINST('事务 +全文检索' IN BOOLEAN MODE);
检索出的记录必须包含“全文检索”和“事务”这两个关键词。
(2) “-”:必须排除指定的关键词
SELECT * FROM bookinfo WHERE MATCH(bookname,content) AGAINST('事务 -全文检索' IN BOOLEAN MODE);
检索出的记录包含“事务”关键词,但是必须不能包含“全文检索”关键词。
(3) “>”:包含该关键词,并且提高该条匹配数据的权重值。
SELECT * FROM bookinfo WHERE MATCH(bookname,content) AGAINST('事务 >全文检索' IN BOOLEAN MODE);
检索出的记录会提高“全文检索”关键词的权重,有“全文检索”关键词的记录排在前面。
(4) “<”:包含该关键词,并且降低该条匹配数据的权重值。
SELECT * FROM bookinfo WHERE MATCH(bookname,content) AGAINST('事务 <全文检索' IN BOOLEAN MODE);
检索出的记录会降低“全文检索”关键词的权重,有“全文检索”关键词的记录排在后面。
(5) “~”将其相关性由正转负,表示拥有该关键词会降低相关性(但不像“-”将之排除),只是权重值降低排在查询显示结果的后面。
SELECT * FROM bookinfo WHERE MATCH(bookname,content) AGAINST('事务 ~全文检索' IN BOOLEAN MODE);
检索出的记录会包含“全文检索”关键词,但是 “全文检索”关键词的相关性由正转负,但是查询结果不排除包含此关键词的记录,只是显示给用户时排列在后面。
(6) “*”:放在关键词尾部的通配符。
SELECT * FROM bookinfo WHERE MATCH(bookname,content) AGAINST('全文*' IN BOOLEAN MODE);
检索出包含“全文”的所有记录。
3.3 查询扩展检索模式(WITH QUERY WXPANSION)
当搜索短语太短时,查询扩展检索是很有用的。先用IN NATURAL LANGUAGE MODE检索,然后把相关的记录中的词添加到查询字符串中进行二次自然语言检索,返回查询得到的结果。可以在搜索“数据库”关键词时查询出“MySQL”、“Oracle”、“DB2”等。第一次查询“数据库”得到一些结果,从这些结果中抽取字符串,得到MySQL、oracle、DB2等几率相当高,最后用“数据库”关键词和这些抽取出来的字符串再做一次查询。
当无法拼出正确的字符串时,第一次用相似的错误字符串进行查询,这时很有可能得到正确的字符串,再用正确的字符串得到想要的查询结果。
SELECT * FROM bookinfo WHERE MATCH(bookname,content) AGAINST('数据库' WITH QUERY EXPANSION) ;
检索出所有与“数据库”关键词相关的记录,如:MySQL、DB2等。
4 删除全文索引
4.1 使用ALTER TABLE删除全文索引
ALTER TABLE bookinfo DROP INDEX ft_booknamecontent;
4.2 使用DROP INDEX删除全文索引
DROP INDEX ft_booknamecontent ON bookinfo;
5 注意事项
1) 创建中文全文索引必须加上with parser ngram。
2) 只能检索被全文索引的那些列,即MATCH()函数中的列必须与创建FULLTEXT索引时的列相同。如MATCH(bookname,content)与FULLTEXT(bookname,content)。若要对索引的多列进行其中某一列的查找时,如bookname列,则必须在这一列单独创建全文索引FULLTEXT(bookname),然后用MATCH(bookname)进行搜索。因此,MATCH()的字段列表一定不能跨表。
3) 默认 MATCH...AGAINST (以自然语言检索模式检索)是以相关性排序,由高到低。
4) 全文索引对于insert、update、delete数据更新操作都很慢。
6 结束语
中文全文检索是从MySQL5.7.6之后内置了n-gram parser全文检索插件后支持的,本文简单介绍了分词大小的设置、全文索引的创建、中文全文索引的应用以及一些相关的注意事项,中文全文检索在检索海量数据的时候,不仅能提高效率,而且提高了查询的准确性。
参考文献:
[1] 曾欢.数据库全文检索方法研究及其应用[D].大连理工大学,2011(11).
[2] 肖文辉.基于MySQL的全文检索系统的研究与引用[J].计算机与信息技术,2008(6).
[3] 楊宝昌.让MySQL支持中文全文检索[J].计算机世界,2006(9).endprint