MySQL的全文本搜索功能进行高级的数据查询和选择
理解全文本搜索
匹配搜索LIKE和正则表达式REGEXP存在的限制
- 性能
匹配表中所有行(极少使用表索引)。被搜索行数不断增加,这些搜索功能可能非常耗时 - 明确控制
很难明确的控制匹配什么和不匹配什么 - 智能化的结果
无法提供一种智能化的选择结果的方法
使用全文本搜索可解决以上问题,MySQL不需要分别查看每个行,不需要分别分析和处理每个词。可以快速有效地决定哪些词匹配(哪些行包含它们),哪些词不匹配,它们匹配的频率等。
MyISAM和InnoDB
MyISAM支持全文本搜索功能,但是InnoDB不支持。
使用全文本搜索
全文本搜索必须搜索被搜索的列。在对列表进行适当设计后,MySQL会自动进行所有的索引和重新索引。
启用全文本搜索支持 FULLTEXT
一般在创建表时启用全文本搜索,CREATE TABLE语句接受FULLTEXT子句,给出被索引列的一个逗号分隔的列表
CREATE TABLE `productnotes` (
`note_id` INT ( 11 ) NOT NULL AUTO_INCREMENT COMMENT '唯一注释ID',
`prod_id` CHAR ( 10 ) NOT NULL COMMENT '产品ID(对应于products表中的prod_id)',
`note_date` datetime NOT NULL COMMENT '增加注释的日期',
`note_text` text COMMENT '注释文本',
PRIMARY KEY ( `note_id` ),
FULLTEXT KEY `note_text` ( `note_text` )
) ENGINE = MyISAM AUTO_INCREMENT = 115 DEFAULT CHARSET = utf8 COMMENT = '产品相关注释表';
- 在定义之后,MySQL自动维护该索引。在增加、更新或删除行是,索引随之自动更新。
- 在创建表时指定FULLTEXT,或者在稍后指定
不要在导入数据时使用FULLTEXT
如果正在导入一个数据到一个新表,此时不应该启用FULLTEXT索引。应先导入所有数据,然后再修改表,定义FULLTEXT。这样有助于更快地导入数据
进行全文本搜索MATCH、AGAINST
使用MATCH()和AGAINST()执行全文本搜索。MATCH指定被搜索的列,AGAINST指定要使用的搜索表达式
SELECT
note_text
FROM
productnotes
WHERE
MATCH ( note_text ) AGAINST ( "rabbit" );
此SELECT语句检索单个列note_text。由于WHERE子句,一个全文本搜索被执行,指定rabbit作为搜索文本。
注意
- 使用完整的MATCH()说明
传递给MATCH()的值必须与FULLTEXT()定义中的相同 - 搜索不区分大小写
除非使用BINARY方式,否则全文本搜索不区分大小写。
使用LIKE和全文本的区别
上述的例子也可以使用LIKE完成
SELECT
note_text
FROM
productnotes
WHERE
note_text LIKE "%rabbit%";
注意其返回的行虽然都为2,但排序的次序不同
使用全文本搜索时,包含词rabbit作为第三个词的行的登记比作为第20个词的行高。
全文本搜索,具有较高等级的行先返回
SELECT
note_text,
MATCH ( note_text ) AGAINST ( "rabbit" ) AS rank
FROM
productnotes;
此SQL语句搜索所有行,使用MATCH和AGAINST用来建立一个计算列,包含全文本搜索计算出的等级值。
等级由MySQL根据行中词的数目、唯一词数目、整个索引中词的总数以及包含该词的行的数目计算出来。
全文本搜索排出那些等级为0的行,按等级以降序排序
- 排序多个搜索项
如果指定多个搜索项,包含多数匹配词的那些行将具有比包含较少词的那些行高的等级值。
使用查询扩展
放宽所返回的全文本搜索结果的范围。
过程
MySQL在使用扩展查询时,会对数据和索引进行俩遍扫描来完成搜索,共分为3步骤
- 进行一个基本的全文本搜索,找出与搜索条件匹配的所有行
- 检查这些匹配行并选择所有有用的词
- 再次进行全文本搜索,不仅使用原来的条件,而且还使用所有有用的词
SELECT
note_text
FROM
productnotes
WHERE
MATCH ( note_text ) AGAINST ( "anvils" WITH QUERY EXPANSION );
使用扩展查询的结果
其返回7行,第一行包含词anvils,因此等级最高。第二行与anvils无关,但包含第一行中的2个词(customer和recommend)所以也被检索出来。第三行也包含这2个相同的词,但因为在文本位置中排序靠后,所以等级为3.
扩展查询极大地增加了返回的行数,但也增加了实际上并不想要的行的数目
布尔文本搜索
即使没有定义FULLTEXT索引也可以使用,但是搜索非常缓慢
布尔方式可以提供如下内容细节:
-
要匹配的词
-
要排斥的词
如果包含这个词则不返回该行,即使该行包含要匹配的词 -
排列提示
指定词的等级 -
表达式分组
-
另外一些内容
-
例:
SELECT
note_text
FROM
productnotes
WHERE
MATCH ( note_text ) AGAINST ( "heavy" IN BOOLEAN MODE );
因为没有指定布尔操作符,其结果与没有指定布尔方式的结果相同。
SELECT
note_text
FROM
productnotes
WHERE
MATCH ( note_text ) AGAINST ( "heavy -rope*" IN BOOLEAN MODE );
匹配包含heavy但不包含以rope开始的词的行,其只返回一行,
全文本布尔操作符
- + 包含,词必须存在
- - 排出,词必须不出现
- > 包含,增加等级值
- < 包含,减少等级值
- () 把词组成子表达式
- ~ 取消一个词的排序值
- * 词尾的通配符
- "" 定义一个短语
全文本搜索的使用说明
- 短词被忽略切葱索引排除(3个或3个以下字符的词,可以更改)
- MySQL自带的内建非用词列表,这些词总是被忽略(可以覆盖)
- 词出现的频率过高,如果词出现在50%以上的行中,则将其作为一个非用词忽略
- 行数少于3行,则全文本搜索不返回结果(每个词或者不出现,或者至少出现在50%的行中)
- 忽略词中的单引号(don't索引为dont)
- 不具有词分隔符(汉语和日语)的语言不能恰当地返回全文本搜索结果
- 仅在MyISAM数据库引擎中支持全文本搜索
Comments | 0 条评论