MySql索引(二)
-- 表列中的单词也是以空格分割来区分
-- 这里指定 MATCH...AGAINST 两次。这不会引起附加的开销,因为 MySQL 优化器会注意到两次是同样的 MATCH...AGAINST 调用,并只调用一次全文搜索代码。
/*
函数 MATCH() 对照一个列名集(一个 FULLTEXT 索引中的一个或多个列的列名)。搜索字符串做为 AGAINST() 的参数给定。搜索以忽略字母大小写的方式执行,预设搜寻是不分大小写,若要分大小写,列的字符集设置要从utf8改成utf8_bin。
虽然同一个表格可以有不同字符集的字段,但是同一个FULLTEXT 索引里的字段必须是同一个字符集与collation。
任何在 stopword 列表上出现的,或太短的(3 个字符或更少的)的单词将被忽略。(可以覆写内建的 stopword 列表。可以修改最少四个字符的设定。 )
搜索的词有一个权重性,如果搜索的词在表中包含它的行太多,则这个搜索词将有较低的权重(可能甚至有一个零权重),否则,它将得到一个较高的权重。然后,权重将被结合用于计算行的相似性。
如果搜索词在表中超过一半的行中出现。则它被有效地处理为一个 stopword (即,一个零语义值的词),不搜索该词。
?
MATCH...AGAINST可以跟所有MySQL语法搭配使用,像是JOIN或是加上其他过滤条件。
?
对于表中的每行记录,MATCH...AGAINST 返回一个相关性值。即,返回的每行与搜索条件之间的相似性尺度。
?
当 MATCH() 被使用在一个 WHERE 子句中时,返回的结果被自动地以相关性从高到底的次序排序。如果即没有 WHERE 也没有 ORDER BY 子句,返回行是不排序的。?
相关性值是正值的浮点数字。零相关性意味着不相似。
相关性的计算是基于:查找单词在表行中的数目、在行中唯一词的数目、在集中词的全部数目和包含一个特殊词的行的数目。
?
到 4.0.1 时,MySQL 也可以使用 IN BOOLEAN MODE 修饰语来执行一个逻辑全文搜索。
IN BOOLEAN MODE的特色:?
不剔除50%以上符合的row。?
不自动以相关性反向排序。?
可以对没有FULLTEXT 索引的字段进行搜寻,但会非常慢。?
限制最长与最短的字符串。?
套用stopwords。
?
逻辑全文搜索支持下面的操作符:
+ 一个领头的加号表示,返回的结果的每行都必须包含有该单词。
- 一个领头的减号表示,包含该单词的行不能出现在返回的结果中。
> 操作符增加包含该单词返回行相似性值的基值。
< 操作符减少包含该单词返回行相似性值的基值。
() 被括号包含的多个词只相当一个词,即在查询时括号里只有一个词可代表该括号与括号外的词相结合做查询,但括号中每个词都会依次被轮到代表该括号,所以与括号外单词会产生多种结合形式,依次做查询条件。
~ 将其相关性由正转负,表示拥有该字会降低相关性,但不像 - 将之排除,只是排在较后面。
* 一个星号是截断操作符,它应该被追加到一个词后,不加在前面。作用类似 LIKE 语句中的 %
"" 把被双引号包含的多个词作为一个词
?
这里是一些示例,在返回结果中:
1.+apple +juice ... 两个词均在被包含
2.+apple macintosh ... 包含词 “apple”,但是如果同时包含 “macintosh”,它的排列将更高一些
3.+apple -macintosh ... 包含 “apple” 但不包含 “macintosh”
4.+apple +(>pie <strudel) ... 包含 “apple” 和 “pie”,或者包含的是 “apple” 和 “strudel” (以任何次序),但是“apple pie” 排列得比 “apple strudel” 要高一点
5.apple* ... 包含 “apple”,“apples”,“applesauce” 和 “applet”
6."some words" ... 可以包含 “some words of wisdom”,但不是 “some noise words”
*/
SELECT *,MATCH (username,city) AGAINST ('>>name300 +thisisname -city100' IN BOOLEAN MODE) FROM mytable WHERE MATCH (username,city) AGAINST ('>>name300 +thisisname -city100' IN BOOLEAN MODE);
/*
全文索引的限制
MATCH() 函数的所有参数必须是从来自于同一张表的列,同时必须是同一个FULLTEXT 索引中的一部分,除非 MATCH() 是 IN BOOLEAN MODE 的。
?
MATCH() 列必须确切地匹配表的某一 FULLTEXT 索引中定义的列,除非 MATCH() 是 IN BOOLEAN MODE 的。
?
AGAINST() 的参数必须是一个常量字符串。
?
?
?
MySQL全文搜寻设定:?
大部分的参数都是启动参数,也就是修改后必须重新启动MySQL。?
有些参数修改必须重新产生索引文件。?
mysql> SHOW VARIABLES LIKE 'ft%';?
?
ft_boolean_syntax ? ?+ -><()~*:""&|?
ft_min_word_len ? ?4?
ft_max_word_len ? ?84?
ft_query_expansion_limit ? 20 ft_stopword_file ? ?(built-in)?
?
ft_min_word_len:最短的索引字符串,默认值为4,修改后必须重建索引文件。?
ft_max_word_len:最长的索引字符串,默认值因版本而不同,余同上一点。?
[mysqld]?
ft_min_word_len=1?
ft_stopword_file:stopword档案路径,若留空白不设定表示要停用stopword过滤,修改后必须重新启动MySQL和重建索引;stopword档案内容可以用分行空白与逗号区隔stopword,但底线和单引号视为合法的字符串字符。?
50%的门坎限制:配置文件在storage/myisam/ftdefs.h,将 #define GWS_IN_USE GWS_PROB 改为 #define GWS_IN_USE GWS_FREQ,然后重新编译MySQL,因为近低门坎会影响数据的精准度,所以不建议如此,可用IN BOOLEAN MODE即可以避开50%的限制。?
ft_boolean_syntax:改变IN BOOLEAN MODE的查询字符,不用重新启动MySQL也不用重建索引。?
修改字符串字符的认定,譬如说将「-」认定为字符串的合法字符:?
方法一:修改storage/myisam/ftdefs.h的true_word_char()与misc_word_char(),然后重新编译MySQL,最后重建索引。?
方法二:修改字符集档,然后在FULLTEXT index的字段使用该字符集,最后重建索引。?
重建索引:?
每个有FULLTEXT index的表格都要这么做。?
mysql> REPAIR TABLE tbl_name QUICK;?
要注意如果用过myisamchk,会导致上述的设定值回复成默认值,因为myisamchk不是用MySQL的设定值。?
解法一:将修改过得设定值加到myisamchk的参数里。?
shell> myisamchk --recover --ft_min_word_len=1 tbl_name.MYI?
解法二:两边都要设定。?
[mysqld]?
ft_min_word_len=1?
[myisamchk]?
ft_min_word_len=1?
解法三:用REPAIR TABLE、ANALYZE TABLE、OPTIMIZE TABLE与ALTER TABLE取代myisamchk语法,因为这些语法是由MySQL执行的。
?
中文全文索引可以建两个表,一个表字段里存中文,一个表对应字段存汉语拼音,两表行必须对应,数据一致,插入时中文转化下汉语拼音,两表都插入
查询时也转化下,全文索引查汉语拼音,然后找到中文表对应行
或者使用mysqlcft中文全文索引插件
?
?
?
查看索引使用情况
如果索引正在工作,Handler_read_key的值将很高,这个值代表了一个行被索引值读的次数,很低的值表明增加索引得到的性能改善不高,因为索引并不经常使用。
Handler_read_rnd_next的值高则意味着查询运行低效,并且应该建立索引补救。这个值的含义是在数据文件中读下一行的请求数。如果你正进行大量的表扫描,该值较高。通常说明表索引不正确或写入的查询没有利用索引。
?
语法:SHOW STATUS LIKE 'Handler_read%';
?
?
MyISAM表的数据文件和索引文件是自动分开的
InnoDB的数据和索引是存储在同一个表空间里面,但可以有多个文件组成
?
虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。
?
?
建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会膨胀很快。