tim&&tip文件

.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: 在tim文件中NodeBlock中包含25~48个entries,每一个entries中包含了一个term的相关数据,FieldSummary中记录了域的一些信息。 图2: NodeBlock有两种类型,如上图所示,第一种是 OuterNode,第二种是 InnerNode。这两种类型的NodeBlock在数据结构上有细微的差别,我们先介绍OuterNode的数据,然后再介绍他们之间的差别以及为什么NodeBlock为什么需要两种类型。 图3:

OuterNode

EntryCount

SuffixLength、StatsLength、MetaLength

Suffix

图4:

Length
SuffixValue

TermStats

图5:

DocFreq
TotalTermFreq

TermMetadata

图6:

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

InnerNode

介绍InnerNode具体的数据结构之前,我们先给出一个场景,如果我们需要处理的term值为下面的情况: 图7: 遍历每一个term,将具有相同前缀"ab"的,并且个数超过25个的term先处理为一个OuterNode,接着前缀值"ab"作为一个term与剩余的term处理为一个InnerNode。 图8: 由于InnerNode中的前缀为"ab"的所有term的Suffix、TermStats、TermMetadata已经存放在.tim文件中,所以在InnerNode只要记录在.tim文件中的偏移位置,即上图中的红色标注的index。所以通过图8与图3就可以看出InnerNode跟OuterNode的数据结构的差异。

FieldSummary

介绍FieldSummary之前,先要声明的是在图1中,只是单个域的.tim文件数据结构,下面是多个域的.tim数据结构 图9: 下面是FieldSummary的数据结构 图10: 图10 中的Field的个数与位置图9中的Field一一对应。

NumFields
FieldNumber
NumTerms
RootCodeLength
RootCodeValue
SumTotalTermFreq
SumDocFreq
DocCount
LongsSize
MinTerm
MaxTerm

DirOffset

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

tip文件的数据结构

图11:

FSTIndex

这块不想详细说了,有些繁琐~,想要深入了FSTIndex的具体内容,大家可以看我的源码注释,在compileIndex(..)方法中:https://github.com/luxugang/Lucene-7.5.0/blob/master/solr-7.5.0/lucene/core/src/java/org/apache/lucene/codecs/blocktree/BlockTreeTermsWriter.java

IndexStartFP

DirOffset

结语

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

点击下载Markdown文件