Lucene 源码系列——tim tip 索引文件

star2017 1年前 ⋅ 884 阅读

  .tim(TermDictionary)文件中存放了每一个 term 的 TermStats,TermStats 记录了包含该 term 的文档数量,term 在这些文档中的词频总和;另外还存放了 term 的 TermMetadata,TermMetadata 记录了该 term 在.doc、.pos、.pay 文件中的信息,这些信息即 term 在这些文件中的起始位置,即保存了指向这些文档的索引;还存放了 term 的 Suffix,对于有部分相同前缀值的 term,只需存放这些 term 不相同的后缀值,即 Suffix。另外还存放了 term 所在域的信息等其他信息,下文中会详细介绍。

  .tip 文件中存放了指向 tim 文件的索引来实现随机访问 tim 文件中的信息,并且。tip 文件还能用来快速判断某个 term 是否存在。

  本文直接介绍了索引文件中每个字段的含义,其具体的生成过程见系列文章索引文件的生成(一)

tim 文件的数据结构

图 1:

1.png

  在 tim 文件中 NodeBlock 中包含了至少 25 个 entries,每一个 entries 中包含了一个 term(或者有相同前缀的 term 集合)的相关数据,FieldSummary 中记录了域的一些信息。

图 2:

2.png

  NodeBlock 有两种类型,如上图所示,第一种是 OuterNode,第二种是 InnerNode。这两种类型的 NodeBlock 在数据结构上有细微的差别(详情见索引文件的生成(六)),我们先介绍 OuterNode 的数据,然后再介绍他们之间的差别以及为什么 NodeBlock 为什么需要两种类型。

图 3:

3.png

OuterNode

  OuterNode 中包含了所有 term 的一些信息(后面会详细介绍包含哪些信息),在 Lucene7.5.0 版本的源码中,按照 term 的大小顺序处理,并且用 3 个 RAMOutputStream 对象,即 suffixWriter、statsWriter、bytesWriter 来记录每一个 term 的 Suffix 信息、TermStats 信息、TermMetadata 信息。在所有的 term 处理结束后,将 3 个 RAMOutputStream 对象中的内容合并写入到。tim 文件中。

EntryCount

  EntryCount 描述了当前的 OuterNode 中包含多个 entries,即包含了多少个 term 的信息。

SuffixLength、StatsLength、MetaLength

  这三个值分别描述了所有 term 的 Suffix、TermStats、TermMetadata 在。tim 文件中的数据长度,在读取。tim 时用来确定读取 Suffix、TermStats、TermMetadata 的范围区间。

Suffix

图 4:

4.png

Length

  term 的后缀长度。

SuffixValue

  term 的后缀值,之前提到按照 term 的大小顺序进行处理的,如果一批 term 具有相同的前缀并且这批 term 的个数超过 25 个,那么这批 term 会被处理为一个 NodeBlock,并且 SuffixValue 只存储除去相同前缀的后缀部分。

TermStats

图 5:

5.png

DocFreq

  DocFreq 描述了包含当前 term 的文档个数。

TotalTermFreq

  TotalTermFreq 描述了 term 在文档中出现的总数,实际存储了与 DocFreq 的差值,目的是尽可能压缩存储,即使用差值存储。

TermMetadata

图 6:

6.png

SingletonDocID

  如果只有一篇文档包含当前 term,那么 SingletonDocID 被赋值这篇文档号,如果不止一篇文档包含当前 term,那么 SingletonDocID 不会写入到。tim 文件中。

LastPosBlockOffset

  如果 term 的词频大于 BLOC_SIZE,即大于 128 个,那么在。pos 文件中就会生成一个 block,LastPosBlockOffset 记录最后一个 block 结束位置,通过这个位置就能快速定位到 term 的剩余的 position 信息,并且这些 position 信息的个数肯定是不满 128 个,可以看 Lucene50PostingsWriter.java 中 finishTerm()的方法。

SkipOffset

  SkipOffset 用来描述当前 term 信息在.doc 文件中 跳表信息的起始位置。

DocStartFP

  DocStartFP 是当前 term 信息在.doc 文件中的起始位置。

PosStartFP

  PosStartFP 是当前 term 信息在。pos 文件中的起始位置。

PayStartFP

  payStartFP 是当前 term 信息在。pos 文件中的起始位置。

InnerNode

  介绍 InnerNode 具体的数据结构之前,我们先给出一个场景,如果我们需要处理的 term 值为下面的情况:



图 7:

7.png

  遍历每一个 term,将具有相同前缀"ab"的,并且个数超过 25 个的 term 先处理为一个 OuterNode,接着前缀值"ab"作为一个 term 与剩余的 term 处理为一个 InnerNode。

图 8:

8.png

  由于 InnerNode 中的前缀为"ab"的所有 term 的 Suffix、TermStats、TermMetadata 已经存放在。tim 文件中,所以在 InnerNode 只要记录在。tim 文件中的偏移位置,即上图中的红色标注的 index。所以通过图 8 与图 3 就可以看出 InnerNode 跟 OuterNode 的数据结构的差异。

FieldSummary

  介绍 FieldSummary 之前,先要声明的是在图 1 中,只是单个域的。tim 文件数据结构,下面是多个域的。tim 数据结构。

图 9:

9.png

  下面是 FieldSummary 的数据结构。

图 10:

10.png

  图 10 中的 Field 的个数与位置图 9 中的 Field 一一对应。

NumFields

  NumFields 描述了。tim 文件中的有多少种域。

FieldNumber

  FieldNumber 记录了当前域的编号,这个编号是唯一的,同时它是从 0 开始的递增值。数值越小,说明该域更早的被添加进了索引。

NumTerms

  NumTerms 记录了当前域中有多少种 term。

RootCodeLength

  RootCodeLength 描述了当前域中的 term 的 FST 数据的长度。

RootCodeValue

  RootCodeValue 描述了当前域中的 term 的 FST 数据。

SumTotalTermFreq

  sumTotalTermFreq 描述了当前域中所有 term 在文档中的总词频。

SumDocFreq

  SumDocFreq 描述了包含当前域中的所有 term 的文档数量。

DocCount

  DocCount 描述了有多少篇文档包含了当前域。

LongsSize

  longsSize 的值只能是 1,2,3 三种,1 说明了当前域只存储了 doc、frequency,2 说明了存储了 doc、frequency,positions,3 说明存储了 doc、frequency,positions、offset。

MinTerm

  当前域中的最小的 term。

MaxTerm

  当前域中的最大的 term。

DirOffset

  DirOffset 记录了 FieldSummary 的信息在。tim 文件中的起始位置。

tip 文件的数据结构

图 11:

11.png

FSTIndex

  FSTIndex 记录了 NodeBlock 在。tim 文件中一些信息,比如说 fp 为 NodeBlock 在。tim 文件中的起始位置,hasTerms 描述 NodeBlock 中是否包含 pendingTerm 对象, isFloor 表示是否为 floor block,然后将这些信息用 FST 算法存储,在前面的博客中有介绍 FST 的存储过程。

IndexStartFP

  IndexStartFP 描述了当前的 FSTIndex 信息在。tip 中的起始位置。

DirOffset

  DirOffset 描述了第一个 IndexStartFP 在。tip 中的位置。

结语

  tim、tip 文件是索引文件中最复杂的实现,加上工作较忙,看了蛮久。如果朋友们想要阅读这部分源码,必须先熟悉 FST 算法,并且源码中 BlockTreeTermsWriter.java 中 pushTerm(BytesRef text)方法在刚开始看时,始终不明白这段代码的意思,尴尬,遇到同样情况的朋友可以简单的理解为它就是为了统计相同前缀的 term 的个数是否达到 25(minItemsInBlock),另外 tip 文件的数据结构没有详细介绍,因为这一块跟 FST 算法紧紧关联,理解了 FST 算法就自然知道了 FSTIndex,而在前面的文章中已经介绍了这个算法,大家可以先去了解下。


本文地址:https://www.6aiq.com/article/1586739207552
本文版权归作者和AIQ共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出

更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: