`

lucene缺点汇总

 
阅读更多

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中的检索服务。

分享到:
评论

相关推荐

    Lucene3.0.3+盘古分词 资源汇总

    《Lucene3.0.3与盘古分词:打造高效搜索引擎》 在信息技术日新月异的时代,搜索引擎已经成为我们获取信息的重要工具。Lucene,作为Apache软件基金会的一个开源项目,是Java语言实现的全文检索引擎库,为开发者提供...

    lucene,lucene教程,lucene讲解

    lucene,lucene教程,lucene讲解。 为了对文档进行索引,Lucene 提供了五个基础的类 public class IndexWriter org.apache.lucene.index.IndexWriter public abstract class Directory org.apache.lucene.store....

    lucene3.0 lucene3.0

    lucene3.0 lucene3.0 lucene3.0 lucene3.0 lucene3.0

    LUCENE索引搜索数据库技术汇总

    **LUCENE索引搜索数据库技术汇总** Lucene是一个高性能、全文检索库,它是Apache软件基金会的顶级项目,被广泛应用于各种搜索引擎的开发。在学习和应用Lucene的过程中,掌握其核心概念和技术至关重要。以下是对...

    lucene-4.7.0全套jar包

    【Lucene 4.7.0 全套JAR包详解】 Lucene是一个开源全文搜索引擎库,由Apache软件基金会开发并维护。它提供了一个高级、灵活的文本搜索API,允许开发者轻松地在应用程序中实现复杂的搜索功能。这次提供的“lucene-...

    lucene in action英文版 lucene 3.30包

    《Lucene in Action》是关于Apache Lucene的权威指南,这本书深入浅出地介绍了全文搜索引擎的构建和优化。Lucene是一个高性能、全文本搜索库,它允许开发人员在应用程序中轻松实现复杂的搜索功能。这本书主要面向...

    Lucene3.5源码jar包

    本压缩包包含的是Lucene 3.5.0版本的全部源码,对于想要深入理解Lucene工作原理、进行二次开发或者进行搜索引擎相关研究的开发者来说,是一份非常宝贵的学习资源。 Lucene 3.5.0是Lucene的一个重要版本,它在3.x...

    Lucene时间区间搜索

    Lucene是一款强大的全文搜索引擎库,广泛应用于各种数据检索场景。在C#环境下,利用Lucene进行时间区间搜索是提高数据检索效率和精确度的重要手段。本篇将深入探讨如何在C#中实现Lucene的时间区间查询匹配,以及涉及...

    Lucene简介.介绍

    【Lucene 简介】 Lucene 是一个强大的开源全文搜索库,由 Java 编写,主要用于为应用程序添加全文检索功能。它不是一个完整的全文搜索引擎应用,而是一个工具包,允许开发者将其集成到自己的软件中,以实现高效、...

    Annotated Lucene 中文版 Lucene源码剖析

    《Annotated Lucene 中文版 Lucene源码剖析》是一本深入探讨Apache Lucene的书籍,专注于源码解析,帮助读者理解这个强大的全文搜索引擎库的工作原理。Lucene是一款开源的Java库,它提供了高效的文本搜索功能,被...

    Lucene示例 BM25相似度计算

    在IT领域,搜索引擎技术是至关重要的,而Lucene作为一个开源全文搜索引擎库,广泛应用于各种文本检索系统中。本文将深入探讨Lucene示例中的BM25相似度计算,旨在帮助初学者理解如何利用Lucene 4.7.1版本构建索引、...

    lucene 2.0 api以及lucene 3.0 api

    **Lucene 2.0 API 和 Lucene 3.0 API 深度解析** Lucene 是一个由 Apache 软件基金会开发的全文搜索引擎库,它为开发者提供了在 Java 应用程序中实现高性能、可扩展的全文搜索功能的能力。Lucene 的 API 设计得相当...

    Lucene的原理完整版pdf

    **Lucene原理详解** Lucene是一个高性能、全文检索库,由Apache软件基金会开发并维护,是Java编程语言中广泛使用的搜索引擎库。它提供了一个简单但功能强大的API,用于索引和搜索文本数据,使得开发者可以轻松地在...

    Java搜索引擎 Lucene

    Java搜索引擎Lucene是一款开源的全文检索库,由Apache软件基金会开发并维护,它为Java开发者提供了强大的文本搜索功能。Lucene的核心目标是让开发者能够快速地在应用中集成高级的搜索功能,使得用户可以轻松地查找和...

    lucene所有的jar包

    《全面解析Lucene jar包:从基础到应用》 在信息技术高速发展的今天,搜索引擎已经成为我们获取信息不可或缺的工具。在Java领域,Lucene作为一个强大的全文搜索引擎库,深受开发者喜爱。本文将详细介绍“lucene所有...

    Lucene资料大全(包括Lucene_in_Action书等)

    标题"Lucene资料大全(包括Lucene_in_Action书等)"表明这是一个包含全面Lucene学习资源的集合,其中最显著的是《Lucene_in_Action》这本书。这是一本广泛认可的关于Apache Lucene的权威指南,通常被简称为LIA,它深入...

    lucene in action源码

    《Lucene in Action》是关于Apache Lucene的权威指南,这本书深入浅出地介绍了全文搜索引擎的构建和优化。源码的提供使得读者可以更直观地理解Lucene的工作原理,这对于学习和开发基于Lucene的搜索应用非常有帮助。...

    lucene.NET 中文分词

    **Lucene.NET 中文分词技术详解** Lucene.NET 是一个高性能、全文检索库,它是Apache Lucene项目在.NET平台上的实现。作为一个开源的搜索引擎框架,Lucene.NET为开发者提供了强大的文本搜索功能。而在处理中文文档...

Global site tag (gtag.js) - Google Analytics