本文链接地址: 关于sphinx – 我有话要说
让子弹飞里面是唱着歌吃着火锅,我这是听着歌写着博客,细细想来,生活本该如此…
前段时间被工作搞得欲仙欲死,终于偷来一点闲暇看看自己究竟整了些啥玩意儿。
此处略去几万字儿,直接进入正题 – sphinx
1. 已经有了数据库的全文检索,为什么需要单独的全文检索引擎
a). 两者相辅相成。全文检索是数据库的有力补充,全文检索并不能替代数据库在应用系统中的作用。当应用系统的数据以大量的文本信息为主时,采用全文检索技术可以极大的提升应用系统的价值。
b). 两者能力有差别。全文检索引擎比mysql做检索更灵活,性能更高。在数据量到一定量级之后全文检索引擎性能高过mysql很多(貌似是10w,没精确试过),另外,前者提供更的匹配模式,评分标准等检索功能。
c). 两者定位有差别。全文搜索引擎专注于搜索,指标是海量数据的查询和索引建立;数据库更加专注于数据本身,对业务所需要的高并发和高吞吐不那么关注。
2. 为什么是sphinx
a). 在全文检索领域,入法眼的就3个,lucene,sphinx,xapian。
基于java的lucene最火,有个基于C的分支;xapian基于C++开发,有成熟的迅搜(xunsearch)支持;基于C++的sphinx,有coreseek和sphinx-for-chinese的二次修改版。语言因素加上不想走分支项目,滤掉lucene,剩下xapian和sphinx。
b). sphinx的高性能(搜索都很费时)高过xapian再加上xapian的api头文件让我凌乱,最终扑向sphinx。
3. sphinx他不是搜索引擎
貌似还有很多人以为sphinx就是搜索引擎了,但我更愿意叫他检索引擎,他的关键能力还在于关键词的匹配上即文本检索。而搜索引擎除了检索系统外还包括更多类似数据挖掘,缓存,相关性预测,去重,纠错以及更复杂的数学模型等等。当然围绕sphinx,我们是可以搭建一套搜索引擎。
4. sphinx提供的接口
a). 传统的api模式(请求发向searchd,searchd回复结果,有原生的和第三方的)
b). sphinxQL(类mysql接口,使用标准mysql的客户端库连接,然后用sphinx扩展的关键字和能力进行检索)
c). sphinxSE(编译进mysql的插件引擎,了解不多)http://sphinxsearch.com/blog/2013/07/23/from-api-to-sphinxql-and-back-again/指出api模式由于打包了所有搜索选项等数据到二进制数据中,所以有额外的开销,且第三方api通常不会随server版本实时更新;sphinxQL性能理论上更改高,且提供一些特殊信息(负载状态,统计特性等)。但目前api方式仍被广泛应用,因为简单且最广为人知。
5. 官方指标
索引建立速度:单核10~15MB/s
搜索速度:单核700 queries/s(100W记录,1.2GB数据,3GHz)
已知应用:分布式索引有30亿,峰值查询5000W queries/day
6. 中文的全文检索(中文分词)
a). 生在天朝要解决的东西很多,中文分词就是其中一项。sphinx本身提供中文的检索支持,但不支持正统的中文词切分,因为中文不像英文有明确的词分隔符。但提供一元分词,即将中文词一个一个的切分。
b). 分词模型常见的,正向/逆向/双向最大匹配,基于词频采集,还有高级点的歧义消除模型,机器学习模型等。不开源的中科院分词前辈咱们不敢奢望,只剩下scws和libmmseg选择,单从api简洁性上scws更胜一筹(friso也值得研究下)。在全文检索中总共有2个地方可能用到分词,建立索引时和搜索时,这里就诞生出两种模式:
实际操作过程中,第二种方案可以通过预先分词以固定分隔符分割的方式预处理,然后检索引擎可按此分隔符进行正确区分;实际运用中,第二种方案由于受限于词库完整性,不可避免会丢掉某些不常见的词进而导致搜索不到。
=======================sphinx进阶=======================
7. 汇总下sphinx搜索本身的能力:过滤(索引源过滤,搜索时过滤),匹配(并,交,相似等),排序(默认排序因子和算法,自定义排序因子,各种排序因子的组合), 组合(子查询(有优化))等。过滤属于边缘属性,重点介绍匹配和评价,因为搜索结果除了数据源的因素外这两个是影响最大的。
a). 匹配模式
sphinx一路走来有过很多匹配模式,最新最被推荐也是功能最强大的是SPH_MATCH_EXTENDED。中文搜索下提供的能力包括但不限于:与,有限制的非,或,字段限制匹配,有序匹配,有限近似匹配,阀值匹配等
上面是最常用的,sphinx官方文档有很详尽描述,使用时需注意运算符优先级。匹配模式只保证能匹配出结果,这只是搜索的第一步,有时排序可能更加重要,因为他跟搜索质量关系更加密切。
b). 评价模型
评价模型通俗的讲就是打分标准,直接影响结果排序,排序的对象就是评价模型所产生的因子。sphinx内建评分器主要有两个因子: phrase proximity, keyword frequencies;前者是词组评分(精准匹配时获得最大分),后者是统计学评分(遵循基于词频的BM25)。这里只考虑SPH_MATCH_EXTENDED,其默认的ranker是SPH_RANK_PROXIMITY_BM25(其他的匹配模式分别对应不同的默认ranker)。
SPH_RANK_PROXIMITY_BM25 = sum(lcs*user_weight)*1000+bm25
SPH_RANK_BM25 = bm25
SPH_RANK_NONE = 1
SPH_RANK_WORDCOUNT = sum(hit_count*user_weight)
SPH_RANK_PROXIMITY = sum(lcs*user_weight)
SPH_RANK_MATCHANY = sum((word_count+(lcs-1)*max_lcs)*user_weight)
SPH_RANK_FIELDMASK = field_mask
SPH_RANK_SPH04 = sum((4*lcs+2*(min_hit_pos==1)+exact_hit)*user_weight)*1000+bm25
SPH_RANK_EXPR = ….
评价模型的灵活性来自于可以自定义(SPH_RANK_EXPR),提供了以下因子:
评价模型直接影响内部属性的值,间接影响排序,根据这些因子可以定制自己的评分标准,然后通过sphinx内建属性@weight表现出来。
c). 排序模型
评价模型的因子在排序模型中抽象成了内部属性@weight(@rank,@relevance),最主流的还是SPH_SORT_EXTENDED模式,绝大部分排序场景都可以用其满足,少部分新闻类数据需要SPH_SORT_TIME_SEGMENTS模式,如果实在不能满足通过SPH_SORT_EXPR模式定制能完成效果。
d). 数据组合
第一种灵活性最差,但是最简单,逻辑单一时使用不错。
第二种灵活性适中,能够应付较为复杂的逻辑,且sphinx内部对子查询有优化,理论性能较高。
第三种最为灵活,但时耗是个严峻的考验。
e). 其他能力
sphinx除了基本的查询数据的能力之外,当然还有很多相关能力,包括但不限于:
8. 实际运用
a). 关键词搜索
这个是最基本的,就不阐述了。常用来用来搭建论坛和博客的内建检索引擎。
b). 关联搜索(http://sphinxsearch.com/blog/2013/05/21/simple-autocomplete-and-correction-suggestion/)
上面是官方博客的一篇文章,简单介绍了搜索框搜索词建议的实现。即完全匹配的相关性条目进行关联展示。体验就像百度搜索框的自动补全建议。
c). 相关词推荐
这个跟关联搜索类似,但是通常出现在相关词推荐中。简单的实现就是提取自己库的关键词作为一个数据源,然后在其中搜索
与查询词相关的词。体验就像百度搜索页底部的”相关搜索”区域。
d). 做缓存
当然理论上是不需要用sphinx来做缓存的,因为数据源通常是数据库,再不进行检索的情况下,从sphinx取数据和从db取数据性能应该说是相近的。
但db通常会有很多并发任务和操作,而sphinx是读静态文件。这里可以用来做带条件的数据读取。
e). 日志分析(http://sphinxsearch.com/blog/2013/07/31/logzilla-big-data-log-analysis-with-sphinx/)
海量日志的查询也是一件蛋疼的事情,至少从db中检索是贼慢的。
利用这个还可以做出很多有意思的玩意儿,例如词的分类建议(制定好类目,然后特定类目下扩充行业分类词库,对查询词进行搜索,然后给出匹配到的类目)等等。
9. 常见的架构
a). 数据量少时 => 单机全量索引 多机部署
全量索引时有效控制文档数及检索文本量。单机包含所有数据,机器用来做负载均衡和容灾。
b). 数据量较大(更新频繁) => 单机全量+增量索引+定时合并 多机部署
全量+增量,有多种逻辑,例如有按文档划分的,也有按其他字段,例如更新时间划分的。需要注意的是文档相同时,增量索引中的数据会覆盖主文档数据。单机包含所有数据,机器用来做负载均衡和容灾。
c). 数据量超大 => 划分数据区+增量索引+定时合并 多机分布式部署
划分数据区,可以按文档,也可以按业务来划分。单机放部分文档或某(几)类业务数据,包含部分数据,其他数据需要从其他节点获取,机器用来做分布式数据存储及负载均衡和容灾。
注:
1). 区分主索引和增量索引是为了更快的重建索引应对数据变更。
索引的重建也面临一些问题:最朴素的处理方式就是定时重建,当然这是个很耗cpu的工作。时间间隔长了,达不到准实时的效果,时间间隔短了,cpu利用率间隔性陡增也是非常影响业务的。目前想到有几种途径可有效缓解,部分方法急需在业务中验证:
2). 划分数据区主要是出于系统优化的考虑(文档越大查询越慢),例如单个索引超过百万级通常就进行拆分(单个索引的理论文档数是亿级别的),还有部分原因是为了便于业务区分。这类似于理论上数据分布 – “复制”和“分片”,前者用于把所有数据放置在所有节点,后者每个节点存放部分数据。
3). 如果db表并发任务较多,myisam引擎有时会出现死锁或阻塞时间过长,这里有几种解决办法:
10. 质量评价标准
搜索的质量评价主观性太强,难以评价,目前主要有三种方式:
a). 精确率/召回率
精确率 = 本次搜索结果中相关文档数 / 本次搜索结果文档总数。
召回率 = 本次搜索结果中相关文档 / 整个文档集合中所有相关文档数。
对搜索引擎和用户而言,召回率太难以估计,没人能翻完所有的相关文档,因此精确率显得更有实际意义。
b). P@n
p@n = 搜索结果中的top(n)中相关文档数 / n
该指标更关注搜索结果排名最靠前的n个文档的结果质量。
c). AP/MAP
AP/MAP = 搜索结果中相关文档的实际位置和 / 搜索结果中相关文档的理想位置和
该指标用以衡量单次或多次查询的平均准确率,理想结果是搜索结果中所有相关文档n都排在top(n),此时AP/MAP = 1。
11. sphinx的roadmap特性和未来
a). 实时索引能力越来越强,性能也越来越好,未来可能作为主推的一种能力。
b). 富媒体的支持,新版本直接能解析json对象的元素,最近一个版本性能也有大幅提升。
作者对sphinx的愿望是把sphinx做到mysql里面去,作为mysql预置的一个引擎。
【参考文档】
官方博客和论坛是目前最好的资料源
国内最大的sphinx应用及论坛
这就是搜索引擎-核心技术详解(张俊林 著)
Sphinx之Coreseek、Sphinx-for-chinaese、Sphinx+Scws 评测
Sphinx + PHP + scws构建MySQL准实时分布式全文检索
Sphinx多线程分布式搜索
基于Sphinx构建准实时更新的分布式通用搜索引擎平台
基于Sphinx+MySQL的千万级数据全文检索(搜索引擎)架构设计
亿级数据的高并发通用搜索引擎架构设计
很好的专业博客
sphinx的各种第三方api,各种插件和管理工具
sphinx charset table
原创文章,转载请注明: 转载自下雨天
本文链接地址: 关于sphinx – 我有话要说