21

tvd&&tvx&&tvm

 3 years ago
source link: https://www.amazingkoala.com.cn/Lucene/suoyinwenjian/2020/1117/178.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

tvd&&tvx&&tvm(Lucene 8.7.0)

  在索引(Indexing)阶段,当某个域被设置为需要记录词向量(term vector)信息后,那么随后在flush阶段,该域对应的词向量将被写入到索引文件.tvd&&tvx&&tvm三个文件中。

1.png

  图1中,域名"content"跟"title"都被设置为需要记录词向量信息,而域名"author"则没有。

索引文件.tvd

2.png

PackedIntsVersion

  PackedIntsVersion描述了压缩使用的方式,当前版本中是VERSION_MONOTONIC_WITHOUT_ZIGZAG。

Chunk

3.png

  在索引阶段,每当处理128篇文档或者已经处理的域值的总长度达到4096,就生成一个chunk。

DocBase

  该字段描述的是chunk中第一篇文档的文档号。

ChunkDocs

  该字段描述的是Chunk中的文档数量。

NumFields

  该字段描述的是Chunk中每篇文档中记录词向量的域的数量。例如图1中只有一篇文档,这篇文档中的就包含了2个记录词向量的域。

  根据Chunk中包含的文档数量,NumFields字段的数据结构各不相同

Chunk中只包含一篇文档

4.png

  如果图1所示,那么NumFields的值为2,并且不会使用压缩存储

Chunk中包含多篇文档

5.png

  当包含多篇文档,那么需要记录每一篇文档中记录词向量的域的数量,然后使用PackedInts存储

FieldNums

  该字段描述的是Chunk中记录词向量的域的种类,根据域的编号来获得域的种类。

(域的种类 - 1) ≤ 7

6.png

token

  token是一个组合值,并且大小是一个字节

  • numDistinctFields:Chunk中记录词向量的域的种类
  • bitsRequired:存储每个域的编号(因为使用了固定位数按位存储)需要的bit数量
  • 左移5位描述了bitsRequired的值最多可以是31
  • 由于一个字节的低五位被用来描述bitsRequired,所以还剩余3个bit可以用来表示numDistinctFields,所以numDistinctFields的值小于等于7时可以跟bitsRequired使用一个字节存储。
FieldNum

  FieldNum即域的编号, 用PackedInts存储。

(域的种类 - 1) > 7

7.png

token

  token是一个组合值,并且大小是一个字节:

  • bitsRequired:存储每一个域的编号需要最少bit位个数
  • 由于numDistinctFields的值大于7,那么在token的高三位用来描述numDistinctFields一部分值,即固定值7,低5位用来描述bitsRequired
  • numDistinctFields - 0x07:存储剩余的差值,例如假设numDistinctFields的值为13,那么7存储在token中、6存储在当前字段

FieldNumOffs

8.png

  FieldNumOffs中存放了chunk中每一篇文档包含的所有域的编号的索引值FieldNumIndex,并且使用PackedInts存储。该索引其实就是fieldNums[ ]数组的下标值,fieldNums[ ]数组的数组元素是Chunk中的域的编号,数组长度是域的种类数。通过这种方式使得不直接存储域的编号,因为域的编号可能跨度很大,由于使用固定位数按位存储,每个域的编号占用的bit数量取决编号最大的,那会导致较大的存储空间,而存储下标值就缓解这个问题。

9.png

  图9中有4个域的编号,如果直接存储域的编号,其中域的编号最大值为255,占用8个bit,故需要 8 *4 = 32个bit。若只存储索引值,那么需要 1 (0) + 1 (1) + 2 (2) + 2 (3) = 6个bit位。

Flags

  Flags用来描述记录词向量的域具体记录哪些信息,这些信息包括:位置position、偏移offset、负载payload信息。flag的值可以是下面3个值的组合:

  • 0x01:包含位置position信息
  • 0x02:包含偏移offset信息
  • 0x04:包含负载payload信息

  比如说 flag = 3,二进制即0b00000011,即该域会记录位置跟偏移信息。

  根据同一个域名在不同的文档中是否有相同的Flag分为不同的情况:

10.png

  图10中,域名"content"、"title"在文档0中会记录位置position、偏移offset、负载payload信息,然而在文档1中只记录位置position、负载payload信息。那么这种情况就称为相同的域名有不相同的flag,反之如果所有记录词向量的域在所有文档中对应的flag都是相同的,那么这种情况称为相同的域名有相同的flag

相同的域名有相同的flag

11.png

  对于某个记录词向量的域名来说,无论它在哪个文档中都记录相同的flag信息,所以只要只要记录一次即可,并且用PackedInts存储,固定值0为标志位,在读取阶段用来区分Flags的不同数据结构。图11中每个flag字段对应一种域,即flag的数量等于记录词向量的域的种类数量

相同的域名有不相同的flag

12.png

  对于一个域名来说,它在不同文档中的flag可能不一样(例如当前文档中,某个记录词向量的域名只记录位置信息,而在下一篇文档中,该域名记录了位置信息跟偏移信息),那么只能所有文档中的所有域的flag,并且用PackedInts存储,固定值1为标志位,在读取阶段用来区分Flags的不同数据结构。图12中,每个Flag对应为某篇文档中的某个记录词向量的域。

TermData

  TermData记录了域值以及Payload信息。

13.png

NumTerms

  NumTerms描述了每一篇文档的每一个域包含的term个数,使用PackedInts存储。

TermLengths

  TermLengths描述了每一篇文档的每一个域中的每一个term的长度,使用PackedInts存储。

TermFreqs

  TermFreqs描述了每一篇文档的每一个域中的每一个term在当前文档中的词频,使用PackedInts存储。

Positions

  Positions描述了每一篇文档的每一个域中的每一个term在当前文档中的所有位置position信息,使用PackedInts存储。

StartOffset

  StartOffset描述了每一篇文档的每一个域中的每一个term的startOffset,使用PackedInts存储。

Lengths

  Lengths描述了每一篇文档的每一个域中的每一个term的偏移长度,使用PackedInts存储。

TermAndPayloads

  使用LZ4算法存储每一篇文档的每一个域中的每一个term值跟payload(如果有的话)。

索引文件.tvd整体数据结构

14.png

索引文件.tvx

15.png

  索引文件.tvx中的字段含义同索引文件.fdx, 不赘述。

索引文件.tvm

16.png

  索引文件.tvm中的字段含义同索引文件.fdm, 不赘述。

  看完这篇文章后,如果感到一脸懵逼, 木有关系,在随后的文章将会详细介绍索引文件tvd&&tvx&&tvm的生成过程。

点击下载Markdown文件


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK