一、概述
MySQL中的全文检索是利用查询关键字和查询列内容之间的相关度进行检索,可以利用全文索引来提高匹配的速度。
二、语法
MATCH (col1,col2,...) AGAINST (expr [search_modifier])
search_modifier: { IN BOOLEAN MODE | WITH QUERY EXPANSION }
例如:SELECT * FROM tab_name WHERE MATCH (col1,col2) AGAINST (search_word);
这里的table需要是MyISAM类型的表,col1、col2需要是char、varchar或text类型,在查询之前需要在col1和col2上建立一个全文索引。
三、检索方式
上面的search_modifier是全文索引的检索方式,MySQL中有三种类型的全文检索:
1、自然语言检索:
全文检索中的默认类型。把查询字符串作为一个短语,如果有不少于50%的行匹配,则认为没有匹配的。想去掉50%的限制,可以修改文件myisam/ftdefs.h里的#define GWS_IN_USE GWS_PROB为#define GWS_IN_USE GWS_FREQ。
查询的字符串大小写不敏感,可以通过指定列的校验码为二进制的来实现大小写敏感。如字符集是latin1,可以指定校验码为latin1_bin。相关性排序的依据:行中的词总数、行中不同的词个数、集合中全部的词总数、查询到的行数。
只能进行单表查询,布尔检索可以进行多表查询。
2、布尔检索:
没有50%的限制。可以用包含特定意义的操作符,如 +、-、"",作用于查询字符串上。查询结果不是以相关性排序的。
3、查询括展检索:
对自然语言检索的一种改动(自动相关性反馈),当查询短语太短时有用。先进行自然语言检索,然后把最相关的一些(系统变量ft_query_expansion_limit的值)行中的词添加到查询字符串中进行二次自然语言检索,查询得到的行作为结果返回。
四、MySQL中全文检索的限制
1、只有MyISAM表支持
2、对大多数的多字节字符集适用,进行全文索引的列必须使用相同的字符集和校验码(collation)。
3、表意性语言,如汉语、日语没有词分界符(英语用空格隔开每个单词),全文分析器无法确定一个词的开始和结尾,所以MySQL中的全文检索不支持。
4、在自然语言检索中,只能检索被全文索引的那些列,如果要对索引的多列进行某一列的检索,必须对这一列单独建立全文索引。布尔检索可以在非索引的列上进行,但会慢一些。
5、against后的参数必须是常量字符串。
6、索引没有记录关键词在字符串中的位置,排序算法太单一。
7、如果索引不在内存中,检索速度会很慢;如果是短语查询,需要索引和数据都在内存中,否则速度会很慢,所以需要更大的key buffer。索引有碎片时也会很慢,所以需要更频繁的optimize table操作。
8、全文索引对于insert、update、delete都很慢。如更改100个词需要进行100次的索引操作而不是1次。
五、与全文检索相关的系统变量:
ft_min_word_len、ft_max_word_len:能被索引和检索的字符串最短长度和最长长度。改变这两个系统变量后需重建全文索引(REPAIR TABLE tbl_name QUICK)。布尔检索时关键字也受这两个量的限制。
ft_stopword_file:停用词的路径,默认在 myisam/ft_static.c文件中。如果设为""(空字符串),则不使用停用词。改变这个系统变量后需重建全文索引(REPAIR TABLE tbl_name QUICK)。
ft_query_expansion_limit:查询括展时取最相关的几个值用作二次查询。
一、全文索引的构建
构建全文索引时把要索引的列连起来(所以不能对其中的某一列进行全文检索)作为一个长的字符串进行索引。构建好的全文索引是一种拥有两层结构的特殊B树索引。第一层是各个关键字(keywords),第二层是关键字所在的文档指针。如下图:
B-tree里存放着一个指向记录的指针和索引列里每个词的关联权重。在创建全文索引后可以用myisam_ftdump在命令行下查看索引的内容:myisam_ftdump
构建好的全文索引里并不存储实际的数据,所以不能用于covering index。
全文索引不会用于排序操作(order by),但自然语言检索中的相关性(relevance)可用于排序。如:
SELECT id, body, MATCH (title,body) AGAINST ('Security implications of running MySQL as root') AS score FROM articles WHERE MATCH (title,body) AGAINS ('Security implications of running MySQL as root');
二、关键字的选取
并不会对索引列里的每个词都建立索引,筛选过程包括去除停用词,去除长度少于ft_min_word_len和大于ft_max_word_len。
三、全文检索实现
首先在全文索引里进行B-tree查找,找到适合的记录的位置,根据存储在树中的每个单独的词的关联度计算出记录的相关度,并根据相关度排序。
四、全文插入实现
当插入一条新的记录时,首先parse记录里的索引列(源文件可参考storage/myisam/ft_parse.c),把它们分成单独的词,忽略停用词(源文件参考ft_stopwords.c、ft_static.c)和长度不符的词。计算出词频,从而计算出词的权重。然后把记录的位置、词的权重、词插入全文索引(源文件参考ft_update.c)。
有话要说