导言:技术是为了解决实际问题的,如果脱离了实际的问题空谈技术,就象是不知道目标而学习一样,效率低且最后一头雾水。因此本文将通过抛出问题--明确目标--解决问题的方式来讲述 全文索引。
抛出问题:
1什么是全文索引,为什么要使用全文索引
扩展问题--分词又是什么?
2使用全文索引的工作原理是什么。
问题阐述:
在讲述什么是全文索引之前,我们来看这么一个场景:
现在经常看到的“站内”搜索等功能。
现在你想搜索 “恶魔法则”。那么网页上就会显示 所有和“恶魔法则”相关的数据。
而这个搜索可以按标题,可以按内容,也可以按作者的综合搜索。如何实现呢?
对于这个问题,一个刚学sql语句两天的朋友都会说 select * from 表名 where 标题 like '%xxx%' or 内容 like '%xxx%' or 作者 like '%xxx%';
没错,这个语句是可以实现这种功能。但是效率却无比的低下。(什么?你问为什么?这个问题请自行思考+google)
那么如何实现这种功能,而又能提高其效率呢?
其中一种方式便是全文索引。
全文索引是为了使得“关键词搜索”功能更加的高效能。
那么什么是全文索引呢?
我们把应用场景具体化:
现在有一个文章管理系统,假设所有的文章内容都是存在数据库的一个字段里面,这个字段最长可以存储3000个字节。
文章的平均长度是2000个字节。
表结构简化如下:
文章id
文章标题
文章内容
1
超级塞亚人
我是超级塞亚人我喜欢吃苹果
而这个系统里有几十万篇文章,你想要在这几十万篇文章里找出包含词语“我喜欢吃苹果”的数据。
上面说过like的效率无比低下。那么如何替换呢?
如果可以以搜索的“关键词”建立一个索引文件,那么问题似乎会变的容易,索引文件的逻辑结构如下:
关键词
文章id
我喜欢吃苹果
1
当你搜索的时候,你会先搜索这个索引表,找到关键词为“我喜欢吃苹果”,然后你就获得了对应的文章id。这样搜索性能就会加快了很多。
或许你现在似懂非懂,再看个详细例子。
我们有这么一张数据表:
文章id
文章标题
文章内容
1
超级塞亚人
我是超级塞亚人我喜欢吃苹果,我不是天朝的人,也不是地球人
2
天朝大国
我大天朝威武,我大天朝13亿人,我大天朝
3
我喜欢游泳
游泳有很多好方法
4
动画片
我儿子喜欢看动画片,尤其是七龙珠,因为里面有塞亚人,而且塞亚人喜欢吃苹果,他们不是地球人
5
运动
我喜欢运动,喜欢跑步,喜欢游泳,喜欢健身,喜欢xxoo
6
打炮
我是一个二战的老兵,这是我的回忆录,我最幸福的时光就是在天朝吃着苹果打炮
7
。。。
8
。。。
9
。。。
然后,根据以上的文章内容,如果建立了一个索引文件(这里忽略索引文件的数据结构,仅仅以一种易于理解的方式呈现):
关键词
文章id
塞亚人
1,4
苹果
1,4,6
天朝
1,2,6
地球
1,4
游泳
3,5
七龙珠
4
喜欢
1,4,5,6
那么当我想搜索 “塞亚人”的时候,这个索引文件直接告诉我在文章id为1和4的文章里有这个词。
这个索引文件就是“全文索引”。
(注:这里的索引文件仅仅易于理解才做成这种表格形势,在实现上有更复杂的数据结构--为了是在这么多个关键词里迅速的找到你想找的关键词啦!这里忽略数据结构的知识,仅从本质上说明全文索引是什么,为了解决什么,即使你没有任何的专业背景知识,只要你学过任何一门数据库的sql语句,相信都能看得懂啦!)
到这里,我们已经解决了一个问题--什么是全文索引。^^
通过观察上面的例子,如果你有心,你可能会思考这么一个问题:
超级塞亚人,是一个词汇呢,还是分为“超级”,“塞亚人”两个词汇呢?
这就是“分词”。
现在有很多专门的分词系统啦!至于算法这里并不多介绍,(因为这不仅仅包括计算机知识啦,想做的更好得需要语言学专家帮助哦)
现在我们已经知道了全文索引和分词。
那么如何使用呢?也就是说你如何使用全文索引和分词的方式来帮助优化你的搜索呢?
大体方案如下:
为了简化概念,我们只从一个固定的套路开始讨论,这样就能省略数据源这些概念,而专心其工作方式啦:
需要工作的程序:索引程序,分词程序,数据库。
工作原理:
1、索引程序从数据库读取数据,比如上面例子中的数据表,索引程序通过sql语句:select 文章id,文章标题,文章内容 from 文章表.获得文章的相关数据
2、索引程序对需要索引的内容进行“分词”,而这里的分词就是调用分词程序啦!
3、索引程序对分好词的一个个词条加入索引文件。
在你写的代码里,原来到数据库----like %xxx%-----的语句
就变成了到索引文件里去查找,从而找到相应的数据(这点相信你已经理解啦!)
好了,原理部分介绍到这。
mysql现在一般使用的版本其实也支持全文索引啦,索引类型为fulltext,只不过他的功能还不够强大:
是对中文的支持不够好,无法智能分词
不过要是纯英文搜索用他还是可以的,只不过要注意有个停止词的概念哦!
那么用什么方法可以快速解决中文搜索的问题呢?
你一定听说过sphinx。(即使没听说过也没关系啦,之后我们会以这个为例子来详细讲解)
coreseek=sphinx+mmesg 这个程序就可以解决这个问题的啦。
sphinx就是上面说的索引程序啦。
mmseg就是分词程序啦。
国内有人修改了sphinx源码,内建和mmseg配合,整合到一起就是coreseek啦!
在下一篇中,
1我们会结合上面的原理,具体分析coreseek的使用参数。
2最后给出具体的分词索引方案。而不仅仅是“照着葫芦画瓢”。
留下思考的问题:
上面说的工作原理当中,sphinx读取数据库生成索引。那么如果sphinx生成完索引,mysql加入了新数据,这不是没有加入到索引当中吗?如何解决?