Fork me on GitHub

构造 IndexWriter 对象(二)

查看来源

系列文章:
构造 IndexWriter 对象(一)

构造一个 IndexWriter 对象的流程总体分为下面三个部分:

  • 设置索引目录 Directory
  • 设置 IndexWriter 的配置信息 IndexWriterConfig
  • 调用 IndexWriter 的构造函数

  在文章构造 IndexWriter 对象(一)中我们讲到了设置 IndexWriter 的配置信息 IndexWriterConfig 中不可配置的内容,接着我们继续介绍可配置的内容。

设置 IndexWriter 的配置信息 IndexWriterConfig

可变配置

  可变配置包含的内容有:MergePolicy、MaxBufferedDocs、RAMBufferSizeMB、MergedSegmentWarmer、UseCompoundFile、CommitOnClose、CheckPendingFlushUpdate。

  可变配置指的是在构造完 IndexWriter 对象后,在运行过程也可以随时调整的配置。

MergePolicy

  MergePolicy 是段的合并策略,它用来描述如何从索引目录中找到满足合并要求的段集合(segment set),在前面的文章了已经介绍了 LogMergePolicyTieredMergePolicy 两种合并策略,这里不赘述。

  MergePolicy 可以通过 IndexWriterConfig.setMergePolicy(MergePolicy mergePolicy)方法设置,在版本 Lucene7.5.0 中默认值使用 TieredMergePolicy,如果修改了 MergePolicy,那么下一次的段的合并会使用新的合并策略。

MaxBufferedDocs、RAMBufferSizeMB

  RAMBufferSizeMB 描述了索引信息被写入到磁盘前暂时缓存在内存中允许的最大使用内存值,而 MaxBufferedDocs 则是描述了索引信息被写入到磁盘前暂时缓存在内存中允许的文档最大数量,这里注意的是,MaxBufferedDocs 指的是一个 DWPT 允许添加的最大文档数量,在多线程下,可以同时存在多个 DWPT(DWPT 的概念见文档的增删改(中)),而 MaxBufferedDocs 并不是所有线程的 DWPT 中添加的文档数量和值

  每次执行文档的增删改后,会调用 FlushPolicy(flush 策略)判断是否需要执行自动 flush(见文档提交之 flush(一)),在 Lucene7.5.0 版本中,仅提供一个 flush 策略,即 FlushByRamOrCountsPolicy,该策略正是依据 MaxBufferedDocs、RAMBufferSizeMB 来判断是否需要执行自动 flush。

  在文档的增删改系列文章中,详细介绍了自动 flush,以及 FlushByRamOrCountsPolicy 的概念,这里不赘述。

  另外在文章中构造 IndexWriter 对象(一)中我们说到一个不可配置值,即 RAMPerThreadHardLimitMB,该值被允许设置的值域为 0~2048M,它用来描述每一个 DWPT 允许缓存的最大的索引量。

图 1:
11.png

如果你没有看过文档的增删改系列文章,那么可以简单的将 DWPT 理解为一个容器,存放每一篇文档对应转化后的索引信息,在多线程下执行文档的添加操作时,每个线程都会持有一个 DWPT,然后将一篇文档的信息转化为索引信息(DocumentIndexData),并添加到 DWPT 中。

  如果每一个 DWPT 中的 DocumentIndexData 的个数超过 MaxBufferedDocs 时,那么就会触发自动 flush,将 DWPT 中的索引信息生成为一个段,如图 1 所示,MaxBufferedDocs 影响的是一个 DWPT。

  如果每一个 DWPT 中的所有 DocumentIndexData 的索引内存占用量超过 RAMPerThreadHardLimitMB,那么就会触发自动 flush,将 DWPT 中的索引信息生成为一个段,如图 1 所示,RAMPerThreadHardLimitMB 影响的是一个 DWPT。

  如果所有 DWPT(例如图 1 中的三个 DWPT)中的 DocumentIndexData 的索引内存占用量超过 RAMBufferSizeMB,那么就会触发自动 flush,将 DWPT 中的索引信息生成为一个段,如图 1 所示,RAMPerThreadHardLimitMB 影响的是所有的 DWPT。

  为什么要提供不可配置 RAMPerThreadHardLimitMB

  • 为避免翻译歧义,直接给出源码中的英文注释
Sets the maximum memory consumption per thread triggering a forced flush if 
exceeded. A DocumentsWriterPerThread(DWPT) is forcefully flushed once it exceeds 
this limit even if the RAMBufferSizeMB has not been exceeded. This is a safety limit to 
prevent a DocumentsWriterPerThread from address space exhaustion due to its internal 
32 bit signed integer based memory addressing. The given value must be less that 2GB
 (2048MB)
  • 上文中的 forcefully flushed 即自动 flush

  MaxBufferedDocs、RAMBufferSizeMB 分别可以通过 IndexWriterConfig.setMaxBufferedDocs(int maxBufferedDocs)IndexWriterConfig.setRAMBufferSizeMB(double ramBufferSizeMB)方法设置,其中 MaxBufferedDocs 默认值为-1,表示在 flush 策略中不依据该值,RAMBufferSizeMB 默认值为 16M。

MergedSegmentWarmer

  MergedSegmentWarmer 即预热合并后的新段,它描述的是在执行段的合并期间,提前获得合并后生成的新段的信息,由于段的合并和文档的增删改是并发操作,所以使用该配置可以提高性能,至于为什么能提高性能,以及提高了什么性能可以看文章执行段的合并(四)关于 生成IndexReaderWarmer 的介绍。

  MergedSegmentWarmer 可以通过 IndexWriterConfig.setMergedSegmentWarmer(IndexReaderWarmer mergeSegmentWarmer)方法设置,MergedSegmentWarmer 默认为 null。

UseCompoundFile

  UseCompoundFile 是布尔值,当该值为 true,那么通过 flush、commit 的操作生成索引使用的数据结构都是复合索引文件,即索引文件.cfs、.cfe

  UseCompoundFile 可以通过 IndexWriterConfig.setUseCompoundFile(boolean useCompoundFile)方法设置,UseCompoundFile 默认为 true。

  注意的是执行段的合并后生成的新段对应的索引文件,即使通过上述方法另 UseCompoundFile 为 true,但还是有可能生成非复合索引文件,其原因可以看文章执行段的合并(三)生成复合索引文件 的流程介绍。

CommitOnClose

  该值为布尔值,它会影响 IndexWriter.close()的执行逻辑,如果设置为 true,那么会先应用(apply)所有的更改,即执行 commit 操作,否则上一次 commit 操作后的所有更改都不会保存,直接退出。

  CommitOnClose 可以通过 IndexWriterConfig.setCommitOnClose(boolean commitOnClose)方法设置,CommitOnClose 默认为 true。

CheckPendingFlushUpdate

  该值为布尔值,如果设置为 true,那么当一个执行添加或更新文档操作的线程完成处理文档的工作后,会尝试去帮助待 flush 的 DWPT,其执行的时机点见下图中红框标注的两个流程点,图 2 为文档的增删改的完整流程图:

图 2:
image.png

结语

  在下一篇文章中,我们继续介绍构造一个 IndexWriter 对象的流程的剩余部分,即调用 IndexWriter 的构造函数。


本文地址:https://www.6aiq.com/article/1586276430450
本文版权归作者和AIQ共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出