在分段的思想下,對數據寫操作的過程如下。
為了提升寫的性能,Lucene並沒有每新增壹條數據就增加壹個段,而是采用延遲寫的策略,每當有新增的數據時,就將其先寫入內存中,然後批量寫入磁盤中。若有壹個段被寫到硬盤,就會生成壹個提交點,提交點就是壹個用來記錄所有提交後的段信息的文件。壹個段壹旦擁有了提交點,就說明這個段只有讀的權限,失去了寫的權限;相反,當段在內存中時,就只有寫數據的權限,而不具備讀數據的權限,所以也就不能被檢索了。從嚴格意義上來說,Lucene或者Elasticsearch並不能被稱為實時的搜索引擎,只能被稱為準實時的搜索引擎。
寫索引的流程如下。
因為索引檢索的過程是:查詢所有段中滿足查詢條件的數據,然後對每個段裏查詢的結果集進行合並,所以為了控制索引裏段的數量,我們必須定期進行段合並操作。但是如果每次合並全部的段,則將造成很大的資源浪費,特別是“大段”的合並。
所以Lucene現在的段合並思路是:根據段的大小先將段進行分組,再將屬於同壹組的段進行合並。但是由於對超級大的段的合並需要消耗更多的資源,所以Lucene會在段的大小達到壹定規模,或者段裏面的數據量達到壹定條數時,不會再進行合並。所以Lucene的段合並主要集中在對中小段的合並上,這樣既可以避免對大段進行合並時消耗過多的服務器資源,也可以很好地控制索引中段的數量。
段合並的主要參數如下。
段合並相關的動作主要有以下兩個:
在段合並前對段的大小進行了標準化處理,通過log MergeFactor SegmentSize
計算得出,其中,MergeFactor表示壹次合並的段的數量,Lucene默認該數量為10;SegmentSize表示段的實際大小。通過上面的公式計算後,段的大小更加緊湊,對後續的分組更加友好。
段分組的步驟如下:
在找到滿足條件的mergeFactor個段時,就需要開始合並了。但是在滿足合並條件的段大於mergeFactor時,就需要進行多次合並,也就是說每次依然選擇mergeFactor個段進行合並,直到該分組的所有段合並完成,再進行下壹分組的查找合並操作。
通過上述幾步,如果找到了滿足合並要求的段,則將會進行段的合並操作。因為索引裏面包含了正向信息和反向信息,所以段合並的操作分為兩部分:壹個是正向信息合並,例如存儲域、詞向量、標準化因子等;壹個是反向信息的合並,例如詞典、倒排表等。在段合並時,除了需要對索引數據進行合並,還需要移除段中已經刪除的數據。