【问题标题】:How does lucene index documents?lucene如何索引文件?
【发布时间】:2011-02-05 19:58:18
【问题描述】:

我阅读了一些关于 Lucene 的文档;我也阅读了此链接中的文档 (http://lucene.sourceforge.net/talks/pisa)。

我不太了解 Lucene 如何索引文档,也不了解 Lucene 使用哪些算法进行索引?

在上面的链接中,它说 Lucene 使用这种算法进行索引:

  • 增量算法:
    • 维护一组段索引
    • 为每个传入文档创建索引
    • 将新索引推入堆栈
    • 设 b=10 为合并因子; M=8

for (size = 1; size < M; size *= b) {
    if (there are b indexes with size docs on top of the stack) {
        pop them off the stack;
        merge them into a single index;
        push the merged index onto the stack;
    } else {
        break;
    }
}

此算法如何提供优化的索引?

Lucene 是否使用 B-tree 算法或任何其他类似的算法进行索引 - 或者它有特定的算法?

【问题讨论】:

  • 这里的大多数答案都是正确的,即第一个 Lucene 创建倒排索引,但这并不能解释该术语索引随后如何搜索的关键点(我相信,这是 OP 实际要求的)。因此,请在下面找到这个相当老的问题的新答案,希望能提供更好的见解。
  • 再次更新了我的答案,因为当前的答案(包括我的!)对于回答 OP 的主要两个问题(Lucene 如何提供优化的索引以及通过哪种特定算法 - 跳过-列表,而不是 B 树,顺便说一句)。希望我的最终更新现在能正确回答实际问题!

标签: algorithm indexing lucene


【解决方案1】:

简而言之,Lucene 使用Skip-Lists在磁盘上构建一个倒排索引,然后使用Finite State Transducer( FST)。但是请注意,Lucene does not (necessarily) load all indexed terms to RAM,正如 Lucene 索引系统的作者 Michael McCandless 所描述的那样。请注意,通过使用 Skip-Lists,索引可以从一个命中遍历到另一个命中,使得 set 之类的事情,尤其是 range 查询 成为可能(很像 B-Trees )。 Wikipedia entry on indexing Skip-Lists 也解释了为什么 Lucene 的 Skip-List 实现被称为 多级 Skip-List - 本质上是为了使 O(log n) 查找成为可能(再次,很像 B-Trees) .

因此,一旦从文档构建了基于Skip-List data structure 的倒排(术语)索引,索引就会存储在磁盘上。然后,Lucene 在 Morfologick 的 FST 实现 loosely inspired 中将这些术语加载(如前所述:可能,只是其中的一部分)到 Finite State Transducer

Michael McCandless(也)做了一个非常好的和简洁的工作 explaining how and why Lucene uses a (minimal acyclic) FST 索引 Lucene 存储在内存中的术语,基本上作为 SortedMap&lt;ByteSequence,SomeOutput&gt;,并给出了 FST 如何工作的基本概念(即 FST 如何压缩字节序列 [即,索引项] 以使该映射的内存使用增长亚线性)。他还指出了 the paper that describes the particular FST algorithm Lucene 的用途。

对于那些好奇为什么 Lucene 使用 Skip-Lists 而大多数数据库使用 (B+)- 和/或 (B)-Trees 的人,请查看 the right SO answer 关于这个问题(Skip-Lists vs. B-Trees) .这个答案给出了一个很好的、深入的解释——本质上,没有让索引的并发更新“更容易”(因为你可以决定不立即重新平衡 B-Tree,从而获得与跳过列表大致相同的并发性能),但是,跳过列表使您不必处理(延迟或不延迟)平衡操作(最终) B-Trees 需要(事实上,正如答案显示/引用的那样,B-Trees 和 [多级] 跳过列表之间的性能差异可能很小,如果其中任何一个“正确完成”。)

【讨论】:

  • Afaik 他们使用 Skip List 而不是 B-tree 来减少磁盘寻道次数,因为 Skip List 的部分驻留在内存中,并且在遍历索引时需要很少的磁盘 IO
【解决方案2】:

您的问题似乎更多是关于索引合并而不是索引本身。

如果您忽略低级细节,索引过程非常简单。 Lucene 从文档中形成所谓的“倒排索引”。因此,如果输入带有文本“To be or not to be”且 id=1 的文档,倒排索引将如下所示:

[to] → 1
[be] → 1
[or] → 1
[not] → 1

基本上就是这样——从单词到包含给定单词的文档的列表的索引。该索引(单词)的每一行称为发布列表。然后,该索引将持久存储在长期存储中。

事实上,事情当然更复杂:

  • Lucene 可能会根据给定的特定分析器跳过一些单词;
  • 可以使用词干算法对单词进行预处理,以减少语言的灵活性;
  • 发布列表不仅可以包含文档的标识符,还可以包含文档中给定单词的偏移量(可能是多个实例)和一些其他附加信息。

还有很多复杂性对于基本理解来说并不那么重要。

理解这一点很重要,Lucene 索引是仅追加。在某个时间点,应用程序决定提交(发布)索引中的所有更改。 Lucene 用索引完成所有的服务操作并关闭它,这样就可以搜索了。提交后索引基本上是不可变的。这个索引(或索引部分)称为。当 Lucene 对查询执行搜索时,它会搜索所有可用的段。

那么问题来了——我们如何更改已索引的文档

使用所谓的kill list,新文档或已索引文档的新版本在新段中被索引,旧版本在以前的段中无效。 Kill list 是已提交索引中唯一可以更改的部分。正如您可能猜到的那样,索引效率会随着时间的推移而下降,因为旧索引可能包含大部分已删除的文档。

这就是合并的用武之地。合并 - 是组合多个索引以使索引整体更有效的过程。合并期间基本上发生的事情是将实时文档复制到新段,而旧段则完全删除。

使用这个简单的过程,Lucene 能够在搜索性能方面保持索引的良好状态。

希望它会有所帮助。

【讨论】:

  • 那么为了首先找到最新的结果,搜索是否会从查看最新的细分开始?所以只是为了澄清 - 假设文档已更新。旧版本的文档被添加到 kill list 中,如果旧段中找到的任何匹配项如果其文档 id 与 kill list 中的 id 匹配,则从搜索结果中删除?
  • 是的,你是对的。唯一要提到的是,最终顺序是使用排序规则定义的(普通情况下的相关性索引),因此搜索段的顺序是不相关的。
【解决方案3】:

这里有一篇相当不错的文章:https://web.archive.org/web/20130904073403/http://www.ibm.com/developerworks/library/wa-lucene/

编辑 12/2014:由于原始版本被删除而更新为存档版本,最近最好的替代方案可能是 http://lucene.apache.org/core/3_6_2/fileformats.html

http://lucene.apache.org/core/4_10_2/core/org/apache/lucene/codecs/lucene410/package-summary.html#package_description 上还有一个更新的版本,但它的信息似乎比旧版本少。

简而言之,当 lucene 索引一个文档时,它会将它分解为多个术语。然后,它将术语存储在索引文件中,其中每个术语都与包含它的文档相关联。你可以把它想象成一个哈希表。

术语是使用分析器生成的,该分析器将每个单词提取到其词根形式。最流行的英语词干算法是 Porter 词干算法:http://tartarus.org/~martin/PorterStemmer/

发出查询时,它会通过用于构建索引的同一分析器进行处理,然后用于查找索引中的匹配项。这提供了与查询匹配的文档列表。

【讨论】:

  • 感谢您的回答和链接。但我听说 Lucene 项目有一个特殊的词干提取器,名为“Snowball”?你听说过吗?
  • 这是一个不同的问题:见lucidimagination.com/search/… 除此之外,看到你的问题模式,我建议你阅读“Lucene in Action”一书:manning.com/hatcher2(第一版有点过时,但可以在死树版本中找到。第二版可以作为电子书购买)。
  • 请修改您的答案,第一个链接是 IBM 链接没有找到 :)
  • 还有,字段怎么进入全图呢?如果查询是针对特定字段的,lucene 如何以及在什么时候知道指向文档的术语不在文档中的任何位置,而是在请求的字段中?
【解决方案4】:

它是inverted index,但没有指定它使用哪种结构。 Index format in lucene资料齐全。
从“文件扩展名摘要”开始。

您首先会注意到它讨论了各种不同的索引。 据我所知,严格来说,这些都没有使用B-tree,但有相似之处——上述结构确实类似于树。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-24
  • 2011-12-13
  • 2012-09-16
  • 1970-01-01
  • 1970-01-01
  • 2013-01-31
相关资源
最近更新 更多