MySQL模糊搜索优化

       InnoDB引擎对FULLTEXT索引的支持是 MySQL5.6 新引入的特性,之前只有MyISAM引擎支持FULLTEXT索引。对于FULLTEXT索引的内容可以使用MATCH()…AGAINST语法进行查询。

        全文搜索的语法:

                MATCH(col1,col2,…) AGAINST (expr[search_modifier])。

        其中MATCH中的内容为已建立FULLTEXT索引并要从中查找数据的列,AGAINST中的expr为要查找的文本内容,search_modifier为可选搜索类型。

        search_modifier的可能取值有:

               IN NATURAL LANGUAGEMODE

               IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION

               IN BOOLEAN MODE

               WITH QUERY EXPANSION

        search_modifier的每个取值代表一种类型的全文搜索,分别为自然语言全文搜索、带查询扩展的自然语言全文搜索、布尔全文搜索、查询扩展全文搜索(默认使用IN NATURAL LANGUAGE MODE)。 这篇博客主要学习的是默认的自然语言全文搜索。

        MySQL中全文索引的关键字为FULLTEXT,目前可对MyISAM表和InnoDB表的CHAR、VARCHAR、TEXT类型的列创建全文索引。全文索引同其他索引一样,可在创建表是由CREATE TABLE语句创建也可以在表创建之后用ALTER TABLE或者CREATE INDEX命令创建(对于要导入大量数据的表先导入数据再创建FULLTEXT索引比先创建索引后导入数据会更快)。

        自然语言全文搜索是MySQL全文搜索的默认搜索方式,实现从一个文本集合中搜索给定的字符串。这里,文本集合指的是指由FULLTEXT索引的一个或者多个列。


示例:

建表,并给content字段加FULLTEXT索引


create table articles (
     id int unsigned auto_increment not null primary key,
     title varchar(200),
     content text,
     fulltext (content)
) engine=InnoDB;


或者

create table articles (  
 id int unsigned auto_increment not null primary key,
     title varchar(200),
     content text,
) engine=InnoDB;
alter table articles add fulltext index_content(content) ;

导入数据:
insert into articles (title,content) values
('MySQL Tutorial','DBMS stands for DataBase ...'),    
('How To Use MySQL Well','After you ...'),   
 ('Optimizing MySQL','In this tutorial we will  ...'),    
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),    
('MySQL vs. YourSQL','In the following database comparison ...'),   
('MySQL Security','When configured properly, MySQL ...');

例1:
select * from articles where match (content) against ('database');



       可以看到,语句查找到了包含指定内容的行。实际上,返回的行是按与所查找内容的相关度由高到低的顺序排列的。这个相关度的值由WHERE语句中的MATCH (…) AGAINST (…)计算所得,是一个非负浮点数。该值越大表明相应的行与所查找的内容越相关,0值表明不相关。该值基于行中的单词数、行中不重复的单词数、文本集合中总单词数以及含特定单词的行数计算得出。

例2: 由上例可知MATCH (…) AGAINST (…)实际上会计算一个相关值,可通过下例来验证。 
select id, match(content) against ('database') as score from articles;



      可以看到,所得结果的第二列即为改行与查找内容的相关度。例1中所得结果的顺序就是按此相关度排列的。

例3: 若想既看到查找到的结果又需要了解具体的相关度,可用下述方法达成。 
select id, content, match (content)  against   ('database')  as score from articles where match (content) against ('databse');

 

      可以看到,通过在查找部分和条件部分分别使用相同的MATCH(…) AGAINST(…)可以同时获取两方面的内容(不会增加额外开销,优化器知道两个MATCH(…) AGAINST(..)是相同的,只会执行一次该语句)。

注意事项 :
       1)默认情况下全文搜索大小写不敏感,可以通过为FULLTEXT索引列所使用的字符集指定一个特定的校对集来改变这种行为。
 
       2)考虑下述两个SELECT语句: 
       1.  SELECT COUNT(*) FROM articles WHERE MATCH (content)  AGAINST('database'); 
       2.  SELECT COUNT(IF(MATCH (content) AGAINST('database'), 1, NULL)) AS count  FROM articles; 
      这两条查询语句均可返回匹配的行数。但第一条语句可以利用基于WHERE从句的索引查找,因此在匹配的行数较少时速度较第二句更快。第二句执行了全表扫描,因此在匹配的行数较多时较第一句更快。
 
       3)MATCH()函数中的列必须与FULLTEXT索引中的列相同。如MATCH(content)与FULLTEXT(content)。若要搜索某两列,如title和content列,则需另外为该两列建全文索引FULLTEXT(title,content),然后用MATCH(title,content)搜索。 

       4)对于InnoDB表MATCH()中的列仅能来自于同一个表,因为索引不能跨多张表(MyISAM表的的布尔搜索因为可以不使用索引,所以可以跨多张表中的列,但速度很慢)。 全文搜索不仅可以搜索类似例1中‘database’这样的单个的单词,还可以搜索句子(这才是其被称为‘全文搜索‘的关键)。

      5)全文搜索把任何数字、字母、下划线序列看作是单词,还可以包含     “ ’ ”    如 aaa’bbb 被解析为一个单词,但aaa’’bbb被解析为两个单词,FULLTEXT解析器自动移除首尾的 “ ’ ” ,如 ’aaa’bbb’ 被解析为 aaa’bbb 。

      6)FULLTEXT解析器用“ ”(空格)、“,”(逗号)“.”(点号)作为默认的单词分隔符,因此对于不使用这些分隔符的语言如汉语来说,FULLTEXT解析器不能正确的识别单词,对于这种情况需做额外处理。 
      7)全文搜索中一些单词会被忽略。首先是过短的单词,InnoDB全文搜索中默认为3个字符,MyISAM默认4个字符,可通过在创建FULLTEXT索引前改变配置参数来改变默认行为,对于InnoDB该参数为:innodb_ft_min_token_size,对于MyISAM为ft_min_word_len;另外stopword列表中的单词会被忽略。stopword列表包含诸如“the”、“or”、“and”等常用单词,这些词通常被认为没有什么语义价值。
      MySQL有内建的停止字列表,但是可以所使用自定义的停止字列表来覆盖默认列表。对于InnoDB控制停止字的配置参数为innodb_ft_enable_stopword,innodb_ft_server_stopword_table,  innodb_ft_user_stopword_table对于MyISAM参数为ft_stopword_file。 
      8)文本集合和查询语句中的单词的权重由该单词在集合或语句中的重要性确定。单词在越多的行中出现则该单词的权重越低,因为这表明其在文本集合中的语义价值较小。反之权重越高。


无论是LIKE搜索还是FULLTEXT搜索,其性能都会随着记录数的增长而下降,因此,若网站项目中的文本搜索数据库记录数庞大的一定规模后,可能需要考虑使用MySQL数据库全文搜索以外的文本搜索解决方案了。


参考资料:http://blog.csdn.net/zyz511919766/article/details/12780173
                  http://www.jb51.net/article/31904.htm
                  http://blog.sina.com.cn/s/blog_48d7f3f40100o6ac.html



  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
针对 MySQL 的模糊查询性能优化,可以考虑以下几个方面: 1. 使用索引:为模糊查询的字段添加索引,可以大大提高查询速度。在模糊查询时,可以使用前缀索引来优化性能。例如,对于一个名为 name 的字段,可以添加一个前缀索引,如 INDEX idx_name (name(10))。 2. 避免在模糊查询中使用通配符开头:通配符开头的模糊查询(如 '%keyword')无法使用索引,会导致全表扫描。尽量避免使用通配符开头,或者考虑使用全文搜索引擎来处理此类需求。 3. 使用全文搜索引擎:MySQL 提供了全文搜索引擎(如 MySQL 的全文索引或第三方搜索引擎,如 Elasticsearch),可以更高效地处理模糊查询。全文搜索引擎可以根据关键词的相关性进行排序,并且支持更复杂的查询操作。 4. 限制查询结果集大小:如果你只需要查询结果中的部分数据,可以通过 LIMIT 关键字限制结果集的大小。这样可以减少查询的数据量,提高查询性能。 5. 数据库优化:定期进行数据库优化操作,包括索引重建、表优化以及统计信息更新等。这些操作可以提高查询性能,并减少模糊查询的执行时间。 6. 数据库分区:如果数据量较大,可以考虑将表进行分区。根据分区规则,可以将数据划分到不同的物理文件中,从而提高查询性能。 7. 使用缓存:对于频繁查询的模糊查询结果,可以考虑使用缓存来提高查询速度。将查询结果缓存在内存中,可以避免每次都进行数据库查询。 这些是一些常见的优化方法,具体的优化策略需要根据实际场景和需求来确定。同时,还可以通过分析慢查询日志、性能监控工具等来找到潜在的性能瓶颈,并进行相应的优化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值