Lucene.net(4.8.0) 學習問題記錄三: 索引的建立 IndexWriter 和索引速度的優化

前言:目前本身在作使用Lucene.net和PanGu分詞實現全文檢索的工做,不過本身是把別人作好的項目進行遷移。由於項目總體要遷移到ASP.NET Core 2.0版本,而Lucene使用的版本是3.6.0 ,PanGu分詞也是對應Lucene3.6.0版本的。不過好在Lucene.net 已經有了Core 2.0版本(4.8.0 bate版),而PanGu分詞,目前有人正在作,貌似已經作完,只是尚未測試~,Lucene升級的改變我都會加粗表示。html

Lucene.net 4.8.0   git

https://github.com/apache/lucenenetgithub

PanGu分詞(能夠直接使用的)apache

https://github.com/SilentCC/Lucene.Net.Analysis.PanGu緩存

 JIEba分詞(能夠直接使用的)安全

https://github.com/SilentCC/JIEba-netcore2.0函數

 

 

Lucene.net 4.8.0 和以前的Lucene.net 3.6.0 改動仍是至關多的,這裏對本身開發過程遇到的問題,作一個記錄吧,但願能夠幫到和我同樣須要升級Lucene.net的人。我也是第一次接觸Lucene ,也但願能夠幫助初學Lucene的同窗。測試

 

一,Lucene 建立索引:IndexWriter

1.IndexWriter的介紹

IndexWriter 是用來建立和維護索引的。IndexWriter的建立:在Lucene4.8.0中,建立IndexWriter對象,須要用到IndexWriterConfig 參數,IndexWriterConfig用來設置一些IndexWriter的屬性優化

IndexWriterConfig _indexWriterConfig = new IndexWriterConfig(Lucene.Net.Util.LuceneVersion.LUCENE_48,analyze)
IndexWriter _indexWriter = new IndexWriter(dir,_indexWriterConfig)

上面的代碼建立了一個基本的IndexWriter對象,每一個基本IndexWriter都必須有兩個必要的屬性:1.操做的索引目錄 dir ;2. 分詞器 analyze .這裏要注意,IndexWriter的分詞器和IndexSearch的分詞器應該是相同的,不然將會影響搜索結果。spa

咱們經過IndexWriterConfig 能夠設置IndexWriter的屬性,已達到咱們但願構建索引的需求,這裏舉一些屬性,這些屬性能夠影響到IndexWriter寫入索引的速度:

IndexWriterConfig.setRAMBufferSizeMB(double);
IndexWriterConfig.setMaxBufferedDocs(int);
IndexWriterConfig.setMergePolicy(MergePolicy)

setRAMBufferSizeMB() 是設置,當IndexWriter添加的文檔的大小超過RAMBufferSizeMB ,IndexWriter就會把在內存中的操做,寫入到硬盤中。具體一點:IndexWriter在執行AddDocuments(寫入文檔),DeleteDocuments(刪除文檔),UpdateDocuments(更新文檔),這些操做的時候,這些操做都會先緩衝到內存中,也就是說執行完這些函數,其實儲存的索引目錄下是沒有任何改變的,當AddDocuments的容量超過上述的屬性的時候,這些操做纔會具體執行到儲存索引的硬盤當中。默認的DEFAULT_RAM_BUFFER_SIZE_MB 是16MB.

 

setMaxBufferedDocs() 是設置,當IndexWriter添加的文檔數量超過MaxBufferedDocs的時候,IndexWriter就會把內存中寫入的文檔,寫到硬盤中,並生成一個新的索引文件segment。關於Lucene的索引結構會在下面說到。

 

setMergePolicy 是設置索引合併的策略,MergePolicy中有一個參數DEFAULT_MAX_CFS_SEGMENT_SIZE 表示索引中最多有多少個segment文件。 

1.1 提升索引的速度 

上面提到了三個IndexWriterConfig的三個屬性。咱們知道,IndexWriter是當緩存中的容量達到必定的限制條件以後,纔開始將緩存中的操做寫入到硬盤中,事實上,若是咱們把限制條件定的值越大,索引的速度是越快的。顯而易見,若是設置RAMBufferSizeMB和MAXBufferedDocu越大,IndexWriter 寫入硬盤的次數就越少,而寫索引的時間耗費大多在對硬盤的操做之上。

IndexWriter寫入索引以後,在索引目錄裏會有不少segment文件。segment文件數量達到MergeFactor (設置合併因子)的時候,IndexWriter會將這些segment文件合併,造成一個新的segment文件,相似於壓縮。而在索引目錄中,若是segment文件越多,則搜索的速度會下降,segement文件越少,搜索的速度也就越快。因此當咱們設置MergeFactor的值越大的時候,搜索的速度就會越快,而合併segement的速度則會下降,也即索引的速度會下降。

 

2. 索引文件的結構

這是,一個索引目錄下的索引文件。結構是這樣的:

  (索引)Index  

     ---(段)Segment  

       ---(文檔)Document

          --- (域)Field

            --- (詞)Term

上面的圖片中,只有一個段,_v6.fdt ;_v6.fdx ....... 都屬於_v6 segment中的內容。而segments_5u 和segments.gen 是段的元數據文件,也即它們保存了段的屬性信息。

  • XXX.fnm保存了此段包含了多少個域,每一個域的名稱及索引方式。
  • XXX.fdx,XXX.fdt保存了此段包含的全部文檔,每篇文檔包含了多少域,每一個域保存了那些信息。
  • XXX.tvx,XXX.tvd,XXX.tvf保存了此段包含多少文檔,每篇文檔包含了多少域,每一個域包含了多少詞,每一個詞的字符串,位置等信息。

上面的是正向信息,還有反向信息就不詳細說了。

 

3.IndexWriter的優化  

在Lucene中IndexWriter.Optimize 用來優化索引,而在Lucene4.8.0中Optimize 已經改名爲ForceMerge,爲的是少讓你使用。IndexWriter的優化實際上就是把Segment文件進行合併,你能夠輸入參數,ForceMerge(segments) 表示,合併到索引目錄裏最多有segments個段文件。而當參數越小的時候,也即合併的文件越多的時候,消耗的時間和空間就越大。很顯然,合併是爲了讓咱們的搜索速度變的更快。

在優化的過程當中,須要當前索引容量兩倍的空間,好比你如今的索引大小是40個G,在優化過程當中,索引的大小會增長到80多個G,而後再合併直到最後只有30多個G。當你的索引更新不是特別頻繁的時候,能夠優化一下,若是更新特別頻繁,那麼調用ForceMerge就會效率很低,這個時候,咱們能夠設置上面提到過的MergeFactor來,讓索引中segments文件少一些。

 

4.IndexWriter的注意事項

1.IndexWriter在操做一個索引的時候會建立一個鎖定文件,Writer.lock 。若是有另外一個IndexWriter要打開這個目錄,將會報錯。

2.IndexWriter實例是徹底線程安全的,多個線程能夠同時調用它的任何方法.

相關文章
相關標籤/搜索