在近实时搜索NRT的系列文章中,我们知道用于读取索引目录中所有索引信息的StandardDirectoryReader实际是使用了一个LeafReader数组封装了一个或者多个SegmentReader,而每一个SegmentReader则对应一个段中的索引信息,如下图所示:
图1:
本篇文章将会介绍在生成SegmentReader的过程中,它获取了哪些具体的索引信息信息,更重要的是,我们还会了解到为什么通过DirectoryReader.openIfChange()(见近实时搜索NRT(三))重新打开一个StandardDirectoryReader的开销会远远的小于DirectoryReader.open()方法(见近实时搜索NRT(一))。
图2:
LeafMetaData包含的信息如下:
下图描述了LeafMetaData包含的信息对应在索引文件中的信息:
图3:
图3中的蓝色箭头描述的是我们可以通过segName找到索引目录中的.si索引文件,可以点击近实时搜索NRT(一)查看segName更详细的介绍。
我们首先介绍下SegmentCoreReaders包含了哪些主要信息:
上文中涉及好几个读取索引文件的操作,这里并不会详细展开读取索引文件的过程,因为太简单了。
不过这里得提一下,使用和不使用复合索引文件cfs&&cfe时,读取索引文件的区别:
图4、图5分别是不使用复合索引文件和使用复合索引文件时索引目录中的文件列表:
图4:
图5:
在不使用复合索引文件的情况下,获得SegmentCoreReaders只需要根据段的前缀名
从索引目录中分别找到每一个非复合索引文件,随后读取即可,而在使用复合索引文件的情况下,我们需要先根据复合索引文件cfs&&cfe,才能读取每一个非复合索引文件的信息。
根据图4、图5的例子,复合索引文件的数据结构如下图所示:
图6:
图6中每一个字段的含义已经在索引文件之cfs&&cfe的文章中介绍,不赘述。
SegmentCoreReaders中包含的索引信息中StoredFieldsReader、TermVectorsReader、PointsReader、NormsProducer是不会发生更改的内容,使得SegmentCoreReaders能够被复用,如果在未来的操作,该段中的索引信息发生更改,那么段中变更的索引信息会以其他索引文件来描述,这便是索引文件之liv、索引文件值.dvm、.dvd、索引文件之fnm,索引信息发生变更的情况以及描述变更的方式如下所示:
所以在我们通过DirectoryReader.openIfChange()获取最新的StandardDirectoryReader时,即使StandardDirectoryReader中某个或多个SegmentReader发生变更,我们可以直接复用SegmentCoreReaders中的索引信息,然后只需要更新(读取)相对开销较小的索引文件之liv、索引文件值.dvm、.dvd、索引文件之fnm这些索引文件即可。
这里的开销指的是什么:
Bits中包含的是段中有效的文档号(live document id),使用FixedBitSet存放这些文档号,通过FixedBitSet其实就知道了那些无效的文档号(原因见FixedBitSet的介绍)。
无效的文档号包含两种情况:
处理出错的文档
的流程点)有效的文档号集合Bits通过索引文件之liv获得。
图7:
图7中,代码的第84、85行,删除了包含"h"的文档号,那么文档0、4、7三篇文档会被删除,即上文中的无效的文档号,那么对应的.liv索引文件如下所示:
图8:
图8中各个字段的名字在文章索引文件之liv中已经介绍,不赘述,图8中的索引信息随后被读取到有效的文档号集合Bits中。
numDocs的值描述的是段中有效的文档号的数量,它的计算方式如下:
numDocs = maxDoc - delCount;
上述的计算方式中,maxDoc描述的是DWPT处理的文档总数(包含添加出错的文档),delCount描述的是无效的文档个数,这两个值在索引文件中的位置如下所示:
图9:
基于篇幅,剩余的内容在下一篇文档中展开介绍。
点击下载附件