本文承接文章索引文件的合并(二)之fdx&&fdt&&fdm,继续介绍剩余的内容,下面先给出索引文件fdx&&fdt&&fdm的合并流程图。
索引文件fdx&&fdt&&fdm的合并流程图
图1:
未配置IndexSort
图2:
如果当前执行合并操作的IndexWriter中没有配置IndexSort,那么依次读取每一个待合并的段,依次读取段中的每篇文档的索引信息即可。回顾下在文章索引文件的合并(二)之fdx&&fdt&&fdm中,当IndexWriter设置了IndexSort,处理过程为从一个优先级队列中的待合并的段中选出一个优先级最高的段,并从这个段的选出一篇文档作为下一次处理的候选者。
根据当前正在处理的某个待合并的段的一些信息,下文中我们称这个段为"旧段",去匹配图2中的两个条件来选择不同的合并方式。合并方式描述的是如何读取旧的索引文件以及如何生成新的索引文件。
图2中的两个条件都是为了筛选出能使用bulk merge的旧段。条件1筛选出能使用bulk merge/optimized merge的旧段,条件2在条件一的基础上筛选出能使用bulk merge的旧段。
条件1由三个子条件组成,他们之间是或"||"的关系,满足三个子条件中的任意一个即认为是满足条件1,那么随后使用 naive merge:
-
子条件一:读取旧段对应使用的reader是否为CompressingStoredFieldsReader对象,只有这种类型的对象才可以使用bulk merge/optimized merge的合并方式,如果不是那么满足子条件一
-
子条件二:在满足子条件一的前提下,如果读取旧段对应使用的reader与新段的版本不一致,那么满足子条件二
- 版本不同,意味着新段跟旧段的索引文件fdx&&fdt&&fdm的数据结构是不一致的,即无法使用bulk merge(下文中会介绍bulk merge为什么需要索引文件的数据结构是一致的)
-
子条件三:在满足子条件一、二的前提下,如果设置了不允许使用bulk merge的参数,那么满足子条件三
这三个条件的判断对应源码 https://github.com/LuXugang/Lucene-7.5.0/blob/master/solr-8.4.0/lucene/core/src/java/org/apache/lucene/codecs/compressing/CompressingStoredFieldsWriter.java 中的下面的代码:
图3:
图3中,matchingFieldReader为null说明旧段不是CompressingStoredFieldsReader对象,即557行代码的注释中所谓的other format。
还有哪些其他的format:
图4:
图4中读取段的reader在Lucene core的模块中主要有两种读取方式,对应上述的两种StoredFieldsReader的实现。
当满足条件一后,旧段中所有文档对应的合并方式都是用naive merge,该合并方式在文章索引文件的合并(二)之fdx&&fdt&&fdm中已经介绍,不赘述。
条件2由5个子条件组成,并且它们需要同时满足。如果满足条件2则使用bulk merge,否则使用optimized merge。另外随后会介绍为什么条件2会由这5个子条件组成:
-
子条件一:旧段中的压缩模式(compressionMode)是否跟新段的一致,如果一致则满足子条件一
- 压缩模式决定了索引文件.fdx中存储域的域值信息的压缩方式。例如在Lucene 8.7.0中引入了两种新的压缩模式,在Lucene 8.7.0版本中合并低版本的段时,条件一就不会满足
-
子条件二:旧段中生成一个Chunk的触发条件之一的chunkSize是否跟新段的一致,如果一致则满足子条件二
- 在文章索引文件的生成(二十四)之fdx&&fdt&&fdm中介绍了chunkSize的概念,chunkSize会影响域值信息的压缩,不赘述
-
子条件三:旧段中的PackedInts的版本是否跟新段的一致,如果一致则满足子条件三
- 在文章索引文件之fdx&&fdt&&fdm中我们说到,Chunk中的DocFieldCounts跟DocLengths字段最终用PackedInts压缩的,如下所示:
图5:
-
子条件四:旧段中不能有被标记为删除的文档,如果没有那么满足子条件四
- 也就是说旧段中不能有索引文件.liv文件
-
子条件五:这个子条件我们暂时不讨论,在介绍玩bulk merge的合并过程后再作介绍
剩余内容看这里:https://www.amazingkoala.com.cn/Lucene/Index/2020/1203/182.html