索引文件之pos&&pay(Lucene 8.4.0)
Lu Xugang Lv6

  position在Lucene中描述的是一个term在一篇文档中的位置,并且存在一个或多个position。

  payload是一个自定义的元数据(mete data)来描述term的某个属性,term在一篇文章中的多个位置可以一一对应多个payload,也可以只有部分位置带有payload。这里提供了一个简单的demo来介绍payload的使用:https://github.com/LuXugang/Lucene-7.5.0/blob/master/LuceneDemo/src/main/java/lucene/AnalyzerTest/PayloadAnalyzer.java。

  offset是一对整数值(a pair of integers),即startOffset跟endOffset,它们分别描述了term的第一个字符跟最后一个在文档中的位置。

  每一个term在所有文档中的position、payload、offset信息在IndexWriter.addDocument()的过程中计算出来,在内存中生成一张倒排表,在flush阶段,通过读取倒排表,将position信息写入到.pos文件中,将payload、offset信息写入到.pay文件中。

  本文介绍的是索引文件.pos、.pay的数据结构,其生成过程见文章索引文件的生成(二)

pay文件的数据结构

图1:

  图1中是仅有一个域的.pay文件的数据结构。

TermPayload

图2:

PackedPayBlock

  每次处理一个term的128个position信息,就会将对应的128个payload信息(不一定每个position都对应一个payload)处理为一个PackedPayBlock。即除了最后一个PackedPayBlock,其他PackedPayBlock中都包含了当前term的128个payload信息。

PackedPayLengthBlock

  PackedPayLengthBlock存放了128个payload的长度数据,并且使用了PackedInts进行了压缩存储,在读取阶段能根据长度数据从PayData中获得对应长度的数据(不明白?请阅读系列文章索引文件的读取(十二)之doc&&pos&&pay)。

这里注意是由于每一个payload的长度无法保证递增,只能使用PackedInts存储原始数据。

SumPayLength

  SumPayLength存放了这128个payload的数据长度(字节数),在读取.pay文件时用来确定128个payload的真实数据在.pay中的数据区间。

PayData

  PayData中存放了128个payload的真实数据。

TermOffset

图3:

PackedOffsetBlock

  跟TermPayload一样的是,都是每次处理一个term的128个position信息后,就会将对应的128个offset信息处理为一个block。

PackedOffsetStartDeltaBlock

  offset是一对整数值(a pair of integers),startOffset跟endOffset分别描述了term的第一个字符跟最后一个在文档中的位置。PackedOffsetStartDeltaBlock存放了128个offset的startOffset值,并且使用了PackedInts进行压缩存储,由于这128个startOffset是个递增的值,所以实际存放了相邻两个offset的startOffset的差值。

PackedOffsetLengthBlock

  PackedOffsetLengthBlock存放了128个offset的startOffset跟endOffset差值,同样使用PackedInts进行压缩存储。

pos文件的数据结构

图4:

  在.pos文件中,TermPosition记录一个term的position信息。

TermPosition

图5:

PackedPosBlock

  每次处理一个term的128个position信息,就会将这些position处理为一个PackedPosBlock。

PackedPosDeltaBlock

  PackedPosDeltaBlock存放了128个位置信息,计算相邻两个position的差值后,利用PackedInts压缩存储。

VIntBlocks && VIntBlock

  如果position的个数不足128个,那么将每一个position处理为一个VIntBlock。(比如说某个term有200个position,那么前128个position处理为一个PackedPosBlock,剩余的72个position处理为72个VIntBlock,72个VIntBlock为一个VIntBlocks)。

PositionDelta

  term的position信息,这是一个差值。PositionDelta的最后一位用来标识当前position是否有payload信息。

PayloadLength

  当前position对应的payload信息的长度,在读取.pos时,用来确定往后读取的一个字节区间。

PayloadData

  当前position对应的payload真实数据。

OffsetDelta

  当前position对应的offset的startOffset值,同样是个差值

OffsetLength

  当前position对应的offset的endOffset与startOffset的差值。

多个域的pay文件的数据结构

图6:

多个域的pos文件的数据结构

图7:

结语

  .pos、.pay、.doc、.tim、.tip文件都是在flush()阶段通过读取倒排表一起生成的,另外.doc跟.pos、.pay文件还有映射关系,在后面介绍.doc文件时候会涉及。

点击下载Markdown文件

 Comments