基于 Mysql 实现一个搜索引擎

前言:

其实 Mysql 很早就支持全文索引了,只不过一直只支持英文的检索,从5.7.6 版本开始,Mysql 就内置了 ngram 全文解析器,用来支持中文、日文、韩文分词。

Mysql 全文索引采用的是倒排索引的原理,在倒排索引中关键词是主键,每个关键词都对应着一系列文件,这些文件中都出现了这个关键词。这样当用户搜索某个关键词时,排序程序在倒排索引中定位到这个关键词,就可以马上找出所有包含这个关键词的文件。

本文测试,基于 Mysql 8.0 版本,数据库引擎采用的是 InnoDB

一、ngram 全文解析器

ngram 就是一段文字里面连续的 n 个字的序列。ngram 全文解析器能够对文本进行分词,每个单词是连续的 n 个字的序列。例如,用 ngram 全文解析器对“你好靓仔”进行分词:

n=1: '你', '好', '靓', '仔' n=2: '你好', '好靓', '靓仔' n=3: '你好靓', '好靓仔' n=4: '你好靓仔'

可以通过以下命令查看 Mysql 默认的 ngram_token_size 大小:

show variables like 'ngram_token_size'

(1)启动 mysqld 命令时指定:

mysqld --ngram_token_size=2
ngram_token_size=2

示例:

select * from article where MATCH(title) AGAINST ('北京旅游' IN NATURAL LANGUAGE MODE);// 不指定模式,默认使用自然语言模式select * from article where MATCH(title) AGAINST ('北京旅游');

上面示例中返回的结果会自动按照匹配度排序,匹配度高的在前面,匹配度是一个非负浮点数。

示例:

// 查看匹配度select * , MATCH(title) AGAINST ('北京旅游') as score from article where MATCH(title) AGAINST ('北京旅游' IN NATURAL LANGUAGE MODE);

示例:

// 无操作符// 包含“约会”或“攻略”select * from article where MATCH(title) AGAINST ('约会 攻略' IN BOOLEAN MODE);
'约会 攻略' 无操作符,表示或,要么包含“约会”,要么包含“攻略”'+约会 +攻略'必须同时包含两个词'+约会 攻略'必须包含“约会”,但是如果也包含“攻略”的话,匹配度更高。'+约会 -攻略'必须包含“约会”,同时不能包含“攻略”。'+约会 ~攻略'必须包含“约会”,但是如果也包含“攻略”的话,匹配度要比不包含“攻略”的记录低。'+约会 +(>攻略 <技巧)'查询必须包含“约会”和“攻略”或者“约会”和“技巧”的记录,但是“约会 攻略”的匹配度要比“约会 技巧”高。'约会*'查询包含以“约会”开头的记录。'"约会攻略"'使用双引号把要搜素的词括起来,效果类似于like '%约会攻略%',例如“约会攻略初级篇”会被匹配到,而“约会的攻略”就不会被匹配。
  • like 只是进行模糊匹配,全文索引却提供了一些语法语义的查询功能,会将要查的字符串进行分词操作,这决定于 Mysql 的词库。
  • 全文索引可以自己设置词语的最小、最大长度,要忽略的词,这些都是可以设置的。
  • 用全文索引去某个列查一个字符串,会返回匹配度,可以理解为匹配的关键字个数,是个浮点数。

而且全文检索的性能也是优于 like 查询的

以下是以 50w 左右数据进行的测试:

// like 查询select * from article where title like '%北京%';

全文索引能快速搜索,但是也存在维护索引的开销。字段长度越大,创建的全文索引也越大,会影响DML语句的吞吐量。数据量不大的情况下可以采用全文索引来做搜索,简单方便,但是数据量大的话还是建议用专门的搜索引擎 ElasticSearch 来做这件事。

更多相关文章

  1. android 之Dialog对话框(简易版)
  2. Android系统源码极速搜索引擎(OpenGrok)
  3. Android实现简易版弹钢琴效果
  4. 为Android开发者定制的搜索引擎
  5. 厂商开始独立,Android你怎么办?
  6. 搜索:ElasticSearch OR MySQL?
  7. 搜索引擎如何判断内容相关性
  8. 搜索引擎相关性计算
  9. 怎么发帖可以让搜索引擎(百度)尽快收录?

随机推荐

  1. HTML显示日期时间代码 - [js 特效代码]
  2. 这个html太奇怪了,源码看不到"下一页"字符
  3. 基于html属性为gulp构建过程添加条件
  4. 为什么v-align中的将文本放在图像下面
  5. 您试图显示配置为只允许执行和脚本权限的
  6. 为什么IE7没有正确地将 块复制到剪贴板?
  7. ThinkPHP生成静态页buildHtml方法
  8. HTML哪些是块级元素,哪些是行内元素、
  9. 使用Semantic-UI垂直对齐div
  10. sublime3安装liveload,实现前端自动F5刷新