从本篇文章开始介绍索引文件合并的过程,其中合并策略、合并调度在之前的文章中已经介绍,没有阅读过这些文章并不会影响对本篇文章的理解。
由于本篇文章是索引文件的合并的开篇文章,故我们先给出各类索引文件合并的先后顺序,如下所示:
图1:
图1中第96行的merge( )方法在被调用后,就开始依次对各种类型的索引文件进行合并,该方法被调用的时机点如下图所示:
图2:
图2中的流程图是执行段的合并的完整流程,其介绍可以阅读系列文章执行段的合并。在红框标注的流程点执行索引文件的合并
中会调用图1中的第96行的merge( )方法,开始索引文件的合并。我们先介绍索引文件fdx&&fdt&&fdm的合并。
图3:
图4:
无论执行哪种索引文件的合并,其输入参数都是同一个MergeState对象,该对象中包含了不同索引文件对应的''reader''数组,数组中的某一个"reader"描述了某个段的索引文件信息,如下图所示:
图5:
所以对于索引文件fdx&&fdt&&fdm的合并,会使用到图5中的StoredFieldsReader[ ]数组,它即图4中的待合并集合。
MergeState对象是何时以及如何生成的:
生成SegmentMerge
中生成MergeState对象图6:
图6中MergeState的构造函数的参数之一是每个待合并的段对应的SegmentReader(CodecReader的实现类)的集合,而在文章SegmentReader(一)中我们知道,SegmentReader中有一个SegmentCoreReaders对象,它包含了段中所有索引文件对应的reader:
所以图5中MergeState对象中所有索引文件对应的''reader''信息都是通过深拷贝从SegmentCoreReaders对象中获取的
图7:
执行该流程点的目的是为了给后续流程中的合并方式给出依据条件,合并方式即图3中的naive merge、optimized merge、bulk merge。这三种合并方式描述了合并后生成的新的索引文件fdx&&fdt&&fdm的生成方式以及读取待合并的索引文件的方式。
统计的逻辑为判断所有的段对应的域名与域的编号的映射关系是否都相同(Computes which segments have identical field name to number mappings)。至于在什么情况下会出现不一致的情况,我们将在介绍索引文件的合并之fnm中展开。
图8:
该流程点通过判断IndexWriter的配置信息IndexWriterConfig来确定是否配置了IndexSort。如果配置了段内排序,那么合并后的段将会段内有序,即段内的文档将会根据IndexWriterConfig中的一个或者多个排序规则进行排序。
待合并的段集合中,要么所有段有相同的段内排序规则,要么都没有段内排序,也就是不存在只有部分段有段内排序,也不存在不同的段有不同的排序规则。
在IndexWriter构造阶段,配置信息IndexSort属于不可变配置,使得通过该IndexWriter对象生成的段总是拥有相同的段内排序规则。另外IndexWriter的构造函数中包含一个Directory对象,如果构造IndexWriter时配置的OpenMode模式为CREATE_OR_APPEND或者APPEND,会先读取Directory对应的索引目录中"旧的"段,它们是其他IndexWriter对象生成的,可能这些"旧的"段中的段内排序规则跟当前IndexWriter中的不一致,那么Lucene不允许读取这些"旧的"的索引文件,会下图的validateIndexSort方法中抛出以下的异常:
图9:
图9中segmentIndexSort为"旧的"索引文件中的段内排序规则,IndexSort为当前IndexWriter的段内排序规则。
为什么Lucene不允许配置了IndexSort的IndexWriter读取段内排序规则不相同的"旧的"段:
无
点击下载附件