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升級的改變我都會加粗表示。

Lucene.net 4.8.0   

https://github.com/apache/lucenenet

PanGu分詞(可以直接使用的)

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的分詞器應該是相同的,否則將會影響搜索結果。

我們通過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實例是完全線程安全的,多個線程可以同時調用它的任何方法.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM