本文承接文章索引檔案的合并(二)之fdx&&fdt&&fdm,繼續介紹剩餘的内容,下面先給出索引檔案fdx&&fdt&&fdm的合并流程圖。
索引檔案fdx&&fdt&&fdm的合并流程圖
圖1:

未配置IndexSort
圖2:
如果目前執行合并操作的IndexWriter中沒有配置IndexSort,那麼依次讀取每一個待合并的段,依次讀取段中的每篇文檔的索引資訊即可。回顧下在文章索引檔案的合并(二)之fdx&&fdt&&fdm中,當IndexWriter設定了IndexSort,處理過程為從一個優先級隊列中的待合并的段中選出一個優先級最高的段,并從這個段的選出一篇文檔作為下一次處理的候選者。
根據目前正在處理的某個待合并的段的一些資訊,下文中我們稱這個段為"舊段",去比對圖2中的兩個條件來選擇不同的合并方式。合并方式描述的是如何讀取舊的索引檔案以及如何生成新的索引檔案。
滿足bulk merge的條件
圖2中的兩個條件都是為了篩選出能使用bulk merge的舊段。條件1篩選出能使用bulk merge/optimized merge的舊段,條件2在條件一的基礎上篩選出能使用bulk merge的舊段。
是否滿足條件1?
條件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?
條件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