1.倒排中以docid排序,这样做的好处是多关键词查询时,merge算法自然,高效.支持phrase query; index merge阶段,处理简单.文件定位快速,倒排压缩高效.但是,它的一个致命的缺陷在于:当某个term的倒排很长时,在处理一次search时,系统需 要对倒排所有元素都进行处理.这样的代价是不可接受的.这就注定了lucene不适合海量数据的检索(当然Local partition的分布式索引可以缓解这样的问题).大量的文献建议采用与query无关的ranking项进行排序.这样一方面可以对倒排剪枝,另一 方面加速search.但这样的方法也有诸如:多关键词结果merge时的低效,索引merge的算法复杂,建立索引的代价大等缺点.克服这些不足,需要 对这两者的优缺点进行相互的扬弃.目前考虑的是采用block的方法,即倒排中以block为基本单位,block之间是ranking降序,而 block内采用docid排序.具体细节这里不详细展开.
2.频繁update的数据将使lucene对disk io影响巨大.lucene的增量索引是通过它的merge算法来实现的.而该merge算法导致频繁的disk操作.一个新的数据的update,可能 导致一部分根本没有变化的索引被重写很多次,并且可能导致很多的小的index segment,造成了search的性能下降,当然,用户可以通过调节几个参数来缓解这个问题.我们可以,兼顾索引效率和检索效率,来重新设计 merge算法(中科院的firtex进行了部分尝试,不过缺点依然明显),可以设计Merge算法对于小的索引可以”越级”与大索引块进行合并,来减少 disk io.根据倒排block设计的思路,我们可以根据某些经验的统计量为每个block预留一定空间,每个单元有标记.这样,我们可以在一定程度上进行 update而根本不需要重写部分索引,从而大大减少disk io.当有大量数据update时候,再采用segment合并的算法进行合并.同时每个block都应该有block head,保留Block的一些统计信息,以便在search的时候及早剪枝.
3。再挑挑刺,Lucene结构很清爽。但唯独一个docid排序,这个假设,遍布与整个代码。惨不忍睹。
4。incremental fetch。lucene不支持从中间取索引。例如:用户取第十页,lucene需要把前面所有的内容都要检索出,然后所有的排序,过滤掉前面的然后返 回。虽然说,这个从用户行为来说(因为大多数用户还是看前面的,不会跳着来),不是什么大问题。但是,这个毕竟可以解决。
5。lucene用java写。但是clucene为了保持与java lucene一致,用了很多难看的写法。并且更新不及时。
6。scorer 和weight写的比较难看。:)
7。doc-partition的模式,当然这个不是lucene本身的问题。doc- partition的方法有着很多不足,诸如全局统计量不准确,disk access大等等,但是大部分文章在综合了系统构架的简单性,网络负载和负载均衡还是普遍认为doc-partition比较优秀(google就是这 种架构),当然针对doc模式的种种不足,也有很多的paper提出了改进的方法。我比较关注的是collection selection function, query log -based partition 和 hybrid architecture。
一 lucene文件的基本构架
lucene文件结构的最大特点是其结构十分紧凑。从文件开始的第一个字节直到最后一个字节都是有效数据,中间没有任何空闲的字节。这样有优点也有缺点, 优点是读取迅速,缺点是修改复杂。因为lucene的作者说lucene并不是为修改频繁的应用设计的,所以,文件结构这么做是无可厚非的。在修改频繁的 环境下,lucene的性能注定会很差。如果是那样的话,您或许需要考虑使用更好的技术,因为增加一个文档到索引其实可以做到十分迅速。
在压缩方面,lucene也采用了一些基本的方法。比如,它对int类型就进行了所谓的byte压缩方法(最初级的方法)。不过,它在String上面采 用的utf-8的编码显然会比utf-16编码占用更多的空间。其它地方还能够看到压缩的是Field Data(域值,.fdt)文件,这个文件保存的是文档包含的域的具体文本(一个文档可以划分为多个域,每个域都是一个字符串),显然这是很大的数据 (zlib好像在这里比较常用,google据说也这样压缩,不过,文本压缩的最好办法显然不是zip,更好的办法还有ppmd)。
————————————————————————————————————————————————————————————————————————————-
二 lucene构建索引的性能
索引,专业点说,包含2种:前向索引和反向索引(倒排索引,inverted index)。前者表示的是某个文档里面的所有词语,后者表示的是包含某个词语的所有文档。对应到Lucene上面,它的前向索引可以认为是Term Vectors(词语向量)相关文件,包含.tvx、.tvd和.tvf这3种文件。前向索引没有什么好评论的,它一般只是做为重组原始数据时候的依据, 其构建十分简单明了。反向索引对应到Lucene上就是index(索引)。Lucene把索引划分成一个一个的segment(块,其实是一个小索 引),直观的说,当有一批新数据到达的时候,我们一般给其构建成一个新的segment,这是因为修改原来的segment的代价很高(并不是说一定很 高,只是lucene采用的文件结构无法简单的加入新的文档)。当一个index包含的segment太多的时候,查找性能就很差了(因为一次查询需要查 询多个segment),需要进行segment的合并。
下面是index和segment的基本结构:
1. index:
index包含4类文件:1)记录segment信息的文件;2)指示索引是否正在更改的标记文件;3)简单组合了若干个文件的复杂文件;4)segment文件及其附属文件。
2. segment:
segment其实是一个小型index,它包含了词汇表、域表、反向索引表、域权重表、词语向量(即前向索引)和已经删除文档表。词汇表包括了本segment里面出现的所有词汇(记得词汇不见得是真的词语,它其实就是索引的字符串)。
三 lucene修改和删除索引的性能
严格的说,lucene底层并不支持对某个文档的修改。因为它的紧密结构抗拒了对文档的直接修改。当需要修改某些文档的时候,可以是这样的:
1. 删除这些文档。这样会使得这些文档ID加入到已经删除的文档表里面。
2. 构建新的索引。这样会生成一个新的segment。
3. 合并索引的所有segment。这样会把所有的segment都合并到一起,构成唯一的一个segment。
大家可以看到,如果仅仅从以上3步来看,lucene的修改索引的性能极差。好在可以利用缓冲,分批的懒惰的进行上面的第2步和第3步。
四 lucene的查询性能
我们从几个方面来分析它的查询性能:
1. 文件个数。文件个数越多,查询的时候需要访问的文件就越多,从而开销也会越大。这是因为要读取的类似数据处在不连续的位置。当你把所有segment都合并成一个之后,这种问题就不存在了。可是,合并segment的花销很大,需要谨慎考虑。
2. 索引词汇。lucene的词汇其实并不是简单的词汇,而是“域+词汇”的保存形式。当域比较多的时候,这种方式的索引词汇构建方式显然会大大降低查找的效 率。不过,值得一提的是,为了降低空间占用,lucene在排序词汇之后,按照如下的形式进行保存: <PrefixLength, Suffix, FieldNum>,这里,PrefixLength表示本词汇借用了前面一个词汇的前面PrefixLength个字符,Suffix表示本词汇 余下的字符串,FieldNum表示本字符串属于的域。
3. 布尔表达式计算。布尔表达式查找的时候,涉及到几条词汇倒排索引的合并的问题。未压缩的索引合并是一个十分容易(不过,算法需要很精细才能优化各种情况) 的事情,可是,lucene的索引经过压缩了(包括前面提到的和相邻数据相减的压缩方法)以及String长度的不确定性,所以,我们无法根据词汇直接定 位到它对应的TermInfo(做为一个变型,你可以在内存中为它做个索引)。于是lucene就使用了 SkipInterval/SkipData(桩,即定位标记)这类结构来加快比较速度,通过和它们的比较,可以简单的跳过多个字节,从而加快了查找速 度。当然了,这种策略比起直接的排序后2分查找显然是慢了许多。
4. 权重计算。权重的计算显然和文件结构没有太大关系。但是,已知的是,lucene保存了每个词汇的出现频率和每个域的权重值,这样就可以通过一些简单的公式计算满足要求的文档对本次查询的匹配度了。
五 Nutch对lucene的改进
Nutch据说还是lucene的作者写的,不过,这次这个高手打算直接和商业搜索引擎进行抗衡,他引入了分布式的构架。Nutch一开始就是分布式的, 它本来就是定位在百以上量级的集群系统(或者网格)上的。对于搜索引擎来说,除了抓取(或者还包含一些前期的数据处理)外,其余的工作都是信息保存、索引 构建和索引查找。Nutch使用的分布式构架,它利用了多台机器的性能来同时构建索引(这一点的可行性在讲MapReduce的google论文里面已经 做了详细的描述),这显然能够提高做索引的速度。在索引查找上面,因为索引查找显然不同于做索引,它要求极高的速度和不高的精度。简单的基于 MapReduce的方法的最大缺点就是速度慢(因为它简单嘛),所以,这位高手强烈建议不要使用分布式的查找方法,因为速度比单机查找还要慢很多(考虑 一下,对于google来说,它的数据量据说达到上百个T,即10万G,没有机器可以挂上这么大的硬盘吧?所以,他们肯定是分布式查询的)。可以肯定的 是,Nutch在搜索方面对lucene的改进就是分布式的做索引。当然了,Nutch比lucene好的地方在于它有了抓取程序(虽然十分的原始)。
-- _____________________________________________________________________________________________________________________________
1、Lucene的搜索算法不适用于网格计算;
Lucene被写出来的时候硬件还没有很大的内存,多处理器也不存在。因此,索引结构是被设计成使用线性的内存开销很小的方式。我花了很长的时间来重写跨度查询算法,并使用多线程内 容(使用双核处理器),但是基于迭代器的目录读取算法几乎不能实现。在一些罕见的场合你能做一些优化并能迭代一个索引通过并行方式,但是大多数场合这是不 可能的。我们遇到的情况是,当我们有一个复杂的,超过50+的内嵌跨度查询,CPU还在空闲但I/O却一直忙碌,甚至在使用了RAMDirectory.
2.一个关闭的API使得继承Lucene成为痛苦
在Lucene的世界中,它被称之为特性。当 某些用户需要得到某些细节,方针是开放类。这导致了大多数的类都是包保护级别的,这意味着你不能够继承他们(除非在你创建的类似在同一个包下,这样做会污 染客户代码)或者你不得不复制和重写代码。更重要的是,如同上面一点提到的,这个严重缺乏OO设计的结构,一些类应该被设为内部类却没有,匿名类被用作复 杂的计算当你需要重写他们的行为。关闭API的理由是让代码在发布前变得整洁并且稳定。虽然想法很光荣,但它再一次让人感到痛苦。因为如果你有一些代码和 Lucene的主要思路并不吻合,你不得不经常回归Lucene的改进到你自己的版本直到你的补丁被接受。
然而当开发者开始越来越长的限制API的更改,你的补丁很少有机会被接受。在一些类和方法上加上final修饰符会让你遇到问题。我认为如果Spring框架有这样的限制,是觉不会流行起来。
3.Lucene并非良好设计
作为一个系统架构师,我倾向认为(1)Lucene有一个非常糟糕 的OO设计。虽然有包,有类的设计,但是它几乎没有任何设计模式。这让我想起一个由C(++)开发者的行为,并且他把坏习惯带到了java中。这造成了, 当你需要自定义Lucene来满足你的需求(你将来必定会遇到这样的需求),你必须面对这样的问题。例如:
几乎没有使用接口。查 询类(例如BooleanQuery,SpanQuery,TermQuery…)都是一个抽象类的子类。如果你要添加其中的一个细节,你会首先想到写一 个接口来描述你扩展的契约,但是抽象的Query类并没有实现接口,你必须经常的变化自己的查询对象到Query中并在本地Lucene中调用。成堆的例 子如(HitCollecor,…)这对使用AOP和自动代理来说也是一个问题.
别扭的迭代实现.没有hasNext()方法,next()方法返回布尔类型并刷新对象内容.这对你想要保持对迭代的元素跟踪来说非常的痛苦.我假定这是故意用来节省内存但是它又一次导致了算法上的杂乱和复杂.
4.积分不能被插件化
Lucene有自己对积分算法的实现,当条件增加时使用 Similarity类。但很快它显示出局限性当你想要表示复杂的积分,例如基于实际匹配和元数据的查询。如果你这样做,你不得不继承Lucene的查询 类。因为Lucene使用类似tf/idf的积分算法,然而在我们遇到的场合,在语意上的积分上Lucene的积分机制并不合适。我们被迫重写每一个 Lucene的查询类使得它支持我们自定义的积分。这是一个问题。
5.跨度查询太慢
这对Lingway公司来说可能是个特殊的问题。我们对跨度查询有很强要 求,Lucene检索结构已经开始添加这一细节,但它们当初可没这么想。最基础的实现导致了复杂的算法并且运行缓慢,尤其是当某些短语在一份文档中重复了 许多次出现。这是为什么我倾向说Lucene是一个高性能的划词检索引擎当你仅仅使用基本的布尔查询时。
6. 没有对集群的内置支持。
如果你创建集群,你可以写出自己对Directory的实现,或是使用Solr或者使用Nutch+Hadoop。Solr和Nutch都 支持Lucene,但不是直接的替代。Lucene是可嵌入的,而你必须支持Solr和Nutch..我认为Hadoop从Lucene团队中产生并不惊 讶:Lucene并不是通用的。它的内在性决定了对大多数场合来说它是非常快速的,但是对大型文档集合时,你不得不排除Lucene。因为它在内核级别上 并没有实现集群,你必须把Lucene转换到别的搜索引擎,这样做并不直接。转换到Solr或者Nutch上的问题会让你遇到许多不必要的麻 烦:Nutch中的集成crawling和Solr中的检索服务。
分享到:
相关推荐
内容概要:本文详细介绍了基于MATLAB GUI界面和卷积神经网络(CNN)的模糊车牌识别系统。该系统旨在解决现实中车牌因模糊不清导致识别困难的问题。文中阐述了整个流程的关键步骤,包括图像的模糊还原、灰度化、阈值化、边缘检测、孔洞填充、形态学操作、滤波操作、车牌定位、字符分割以及最终的字符识别。通过使用维纳滤波或最小二乘法约束滤波进行模糊还原,再利用CNN的强大特征提取能力完成字符分类。此外,还特别强调了MATLAB GUI界面的设计,使得用户能直观便捷地操作整个系统。 适合人群:对图像处理和深度学习感兴趣的科研人员、高校学生及从事相关领域的工程师。 使用场景及目标:适用于交通管理、智能停车场等领域,用于提升车牌识别的准确性和效率,特别是在面对模糊车牌时的表现。 其他说明:文中提供了部分关键代码片段作为参考,并对实验结果进行了详细的分析,展示了系统在不同环境下的表现情况及其潜在的应用前景。
嵌入式八股文面试题库资料知识宝典-计算机专业试题.zip
嵌入式八股文面试题库资料知识宝典-C and C++ normal interview_3.zip
内容概要:本文深入探讨了一款额定功率为4kW的开关磁阻电机,详细介绍了其性能参数如额定功率、转速、效率、输出转矩和脉动率等。同时,文章还展示了利用RMxprt、Maxwell 2D和3D模型对该电机进行仿真的方法和技术,通过外电路分析进一步研究其电气性能和动态响应特性。最后,文章提供了基于RMxprt模型的MATLAB仿真代码示例,帮助读者理解电机的工作原理及其性能特点。 适合人群:从事电机设计、工业自动化领域的工程师和技术人员,尤其是对开关磁阻电机感兴趣的科研工作者。 使用场景及目标:适用于希望深入了解开关磁阻电机特性和建模技术的研究人员,在新产品开发或现有产品改进时作为参考资料。 其他说明:文中提供的代码示例仅用于演示目的,实际操作时需根据所用软件的具体情况进行适当修改。
少儿编程scratch项目源代码文件案例素材-剑客冲刺.zip
少儿编程scratch项目源代码文件案例素材-几何冲刺 转瞬即逝.zip
内容概要:本文详细介绍了基于PID控制器的四象限直流电机速度驱动控制系统仿真模型及其永磁直流电机(PMDC)转速控制模型。首先阐述了PID控制器的工作原理,即通过对系统误差的比例、积分和微分运算来调整电机的驱动信号,从而实现转速的精确控制。接着讨论了如何利用PID控制器使有刷PMDC电机在四个象限中精确跟踪参考速度,并展示了仿真模型在应对快速负载扰动时的有效性和稳定性。最后,提供了Simulink仿真模型和详细的Word模型说明文档,帮助读者理解和调整PID控制器参数,以达到最佳控制效果。 适合人群:从事电力电子与电机控制领域的研究人员和技术人员,尤其是对四象限直流电机速度驱动控制系统感兴趣的读者。 使用场景及目标:适用于需要深入了解和掌握四象限直流电机速度驱动控制系统设计与实现的研究人员和技术人员。目标是在实际项目中能够运用PID控制器实现电机转速的精确控制,并提高系统的稳定性和抗干扰能力。 其他说明:文中引用了多篇相关领域的权威文献,确保了理论依据的可靠性和实用性。此外,提供的Simulink模型和Word文档有助于读者更好地理解和实践所介绍的内容。
嵌入式八股文面试题库资料知识宝典-2013年海康威视校园招聘嵌入式开发笔试题.zip
少儿编程scratch项目源代码文件案例素材-驾驶通关.zip
小区开放对周边道路通行能力影响的研究.pdf
内容概要:本文探讨了冷链物流车辆路径优化问题,特别是如何通过NSGA-2遗传算法和软硬时间窗策略来实现高效、环保和高客户满意度的路径规划。文中介绍了冷链物流的特点及其重要性,提出了软时间窗概念,允许一定的配送时间弹性,同时考虑碳排放成本,以达到绿色物流的目的。此外,还讨论了如何将客户满意度作为路径优化的重要评价标准之一。最后,通过一段简化的Python代码展示了遗传算法的应用。 适合人群:从事物流管理、冷链物流运营的专业人士,以及对遗传算法和路径优化感兴趣的科研人员和技术开发者。 使用场景及目标:适用于冷链物流企业,旨在优化配送路线,降低运营成本,减少碳排放,提升客户满意度。目标是帮助企业实现绿色、高效的物流配送系统。 其他说明:文中提供的代码仅为示意,实际应用需根据具体情况调整参数设置和模型构建。
少儿编程scratch项目源代码文件案例素材-恐怖矿井.zip
内容概要:本文详细介绍了基于STM32F030的无刷电机控制方案,重点在于高压FOC(磁场定向控制)技术和滑膜无感FOC的应用。该方案实现了过载、过欠压、堵转等多种保护机制,并提供了完整的源码、原理图和PCB设计。文中展示了关键代码片段,如滑膜观测器和电流环处理,以及保护机制的具体实现方法。此外,还提到了方案的移植要点和实际测试效果,确保系统的稳定性和高效性。 适合人群:嵌入式系统开发者、电机控制系统工程师、硬件工程师。 使用场景及目标:适用于需要高性能无刷电机控制的应用场景,如工业自动化设备、无人机、电动工具等。目标是提供一种成熟的、经过验证的无刷电机控制方案,帮助开发者快速实现并优化电机控制性能。 其他说明:提供的资料包括详细的原理图、PCB设计文件、源码及测试视频,方便开发者进行学习和应用。
基于有限体积法Godunov格式的管道泄漏检测模型研究.pdf
嵌入式八股文面试题库资料知识宝典-CC++笔试题-深圳有为(2019.2.28)1.zip
少儿编程scratch项目源代码文件案例素材-几何冲刺 V1.5.zip
Android系统开发_Linux内核配置_USB-HID设备模拟_通过root权限将Android设备转换为全功能USB键盘的项目实现_该项目需要内核支持configFS文件系统
C# WPF - LiveCharts Project
少儿编程scratch项目源代码文件案例素材-恐怖叉子 动画.zip
嵌入式八股文面试题库资料知识宝典-嵌⼊式⼯程师⾯试⾼频问题.zip