您的位置:首页 > 数据库 > MySQL

MYSQL必知必会读书笔记 第十八章 全文本检索

2016-05-11 15:44 211 查看
并不是所有的引擎都支持全文本检索。在MYSQL中最常用的两个引擎为MyISAM和InnoDB,前者支持全文搜索,而后者不支持。在LIKE和正则中搜索。这种搜索机制非常常用但是存在几个重要的限制。

性能-----通配符和正则表达式匹配通常要求MySQL尝试匹配表中所有行(而且这些搜索极少使用表索引)。因此,由于被搜索行数的不断增加,这些搜索可能非常耗时。

明确控制-----使用通配符和正则表达式匹配,很难应该说并不总能明确地控制匹配什么和不匹配什么。例如,指定一个词必须匹配,一个词必须不匹配,而且一个词仅在第一个词明确匹配的时候才可以匹配或者才可以不匹配。

智能化的结果-----基于通配符和正则表达式的搜索提供了非常灵活的搜索,但是它们都不能提供一种智能化的选择结果的方法。例如一个特殊词的搜索将会返回包含该词的所有行,而不是区分包含单个匹配的行和包含多个匹配的行。

使用全文本搜索:为了进行全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断地重新索引。在对表列进行适当设计后,MySQL会自动进行所有的索引和重新索引。在索引之后,SELECT可与MATCH()和Against()一起使用以实际执行搜索。

启用全文本搜索支持:

CREATE TABLE productnotes(

note_id int NOT NULL AUTO_INCREMENT,

prod_id char(10) NOT NULL,

note_date datetime NOT NULL,

note_text text NULL,

PRIMARY KEY (note_id),

FULLTEXT(note_text)

)ENGINE=MyISAM;

需要注意的是在使用FULLTEXT 更新索引要花时间,所以吐过正在导入数据到一个新表,此时不应该启用FULLTEXT索引。应该首先导入所有数据,然后再修改表,这样更有助于更快地导入数据。且使索引的总时间小于在导入每行时分别进行索引所需的总时间。

进行全文本搜索:

SELECT note_text FROM productnotes WHERE Match(note_text) Against('rabbit');

注意的是:传递给Match()的值必须与FULLTEXT()定义中相同。如果指定多个列,则必须列出它们而且次序正确。除非使用BINARY方式,否则全文搜索不区分大小写。

实际上以上语句也可以通过LIKE完成,

SELECT note_text FROM productnotes WHERE note_text LIKE '%rabbit%';

但是返回的数据并不是很有顺序,而全文搜索中具有优先级,为了演示排序的工作,可以使用以下语句:

SELECT note_text, Match(note_text) Against('rabbit') AS rank FROM productnotes;

如果指定多个搜索项,则包含多数匹配次的那些行具有比包含较少词(或仅有一个匹配词)的那些行高的等级值。

使用查询扩展:查询扩展的过程为:

首先进行一个基本的全文搜索,找出与匹配条件匹配的所有行。

其次,MYSQL检查这些匹配行并选择所有有用的词

再其次,MYSQL再次进行全文本搜索,这次不仅使用原来的条件,而且使用所有有用的词。

SELECT note_text FROM productnotes WHERE Match(notetext) Against('anvils' WITH QUERY EXPANSION);

布尔文本搜索:具体细节如下

要匹配的词;

要排斥的词

排列提示(指定某些词比其他词更重要,更重要的词等级更高)

表达式分组;

即使没有FULLTEXT索引也可以使用 布尔方式不同于迄今为止使用的全文本搜索语法的地方在于,即使没有定义FULLTEXT索引,也可以使用它,但是这是一种非常缓慢的操作。

SELECT note_text FROM productnotes WHERE Match(note_text) Against('heavy' IN BOOLEAN MODE);

虽然这个例子的结果与没有使用 IN BOOLEAN MODE的相同,但其行为有一个重要的差别:

为了匹配包含heavy 但不包含任意以rope开始的词的行,可使用以下查询:

SELECT note_text FROM productnotes WHERE Match(note_text) Against ('heavy -rope*' IN BOOLEAN MODE);

包含rabbit和bait的行(同时包含)词的操作:

SELECT note_text FROM productnotes WHERE Match(note_text) Against('+rabbit +bait' IN BOOLEAN MODE);

至少包含一个

SELECT note_text FROM productnotes WHERE Match(note_text) Against('rabbit bait' IN BOOLEAN MODE);

匹配,增加前者的等级,降低后者的等级。

SELECT note_text FROM productnotes WHERE Match(note_text) Against ('>rabbit <carrot' IN BOOLEAN MODE);

搜索匹配词safe和combination,降低后者的等级。

SELECT note_text FROM productnotes WHERE Match(note_text) Against ('+rabbit +(<carrot)' IN BOOLEAN MODE);

注意的是在布尔方式中,不按等级值降序排列返回的行。
全文本搜索使用说明:

1.在索引全文本数据时,短词忽略且从索引中排除。短词定义为那些具有3个或者3个以下字符的词(如果需要这个数目可以更改)

2.Mysql带有一个内建的非用词列表,这些词在索引全文本数据时会被忽略,如果需要可以覆盖这个列表。

3.许多词出现的频率很高,搜索它们没有用处(返回太多结果)。因此,MySQL规定一条50%规则,如果一个词出现在50%以上的行中,将它作为一个非用词忽略。50%规则不用于IN BOOLEAN MODE 中。

4.如果表中的行数少于3行,则全文本搜索不返回结果(因为每个词出现或不出现,或者至少出现在50%的行中)

5.忽略词中的单引号 don't 索引为 dont

6. 不具有词分隔符的语言如汉语不能恰当的返回全文本搜索结果。

MySQL中没有邻近操作符,邻近搜索是许多全文本搜索支持的一个特性,它能搜索相邻的词(在句子中、相同的段落中或者在特定数目的词的部分中,等等)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: