如何提高Lucene的索引速度(轉)

原文地址

這篇文章主要介紹瞭如何提高Lucene的索引速度。介紹的大部分思路都是很容易嘗試的,當然另外一部分可能會加大你程序的複雜度。所以請確認索引速度確實很慢,而且很慢的原因確實是因爲Lucene自身而造成的。推薦姐妹篇:如何提高和優化Lucene搜索速度

 

確認你在使用最新的Lucene版本。

儘量使用本地文件系統

遠程文件系統一般來說都會降低索引速度。如果索引必須分佈在遠程服務器,請嘗試先在本地生成索引,然後分發到遠程服務器上。

 

使用更快的硬件設備,特別是更快的IO設備

在索引期間複用單一的IndexWriter實例

使用按照內存消耗Flush代替根據文檔數量Flush

Lucene 2.2之前的版本,可以在每次添加文檔後調用ramSizeInBytes方法,當索引消耗過多的內存時,然後在調用flush()方法。這樣做在索引大量小文檔或者文檔大小不定的情況下尤爲有效。你必須先把maxBufferedDocs參數設置足夠大,以防止writer基於文檔數量flush。但是注意,別把這個值設置的太大,否則你將遭遇Lucene-845BUG。不過這個BUG已經在2.3版本中得到解決。

Lucene2.3之後的版本。IndexWriter可以自動的根據內存消耗調用flush()。你可以通過writer.setRAMBufferSizeMB()來設置緩存大小。當你打算按照內存大小flush後,確保沒有在別的地方設置MaxBufferedDocs值。否則flush條件將變的不確定(誰先符合條件就按照誰)。

 

在你能承受的範圍內使用更多的內存

flush前使用更多的內存意味着Lucene將在索引時生成更大的segment,也意味着合併次數也隨之減少。在Lucene-843中測試,大概48MB內存可能是一個比較合適的值。但是,你的程序可能會是另外一個值。這跟不同的機器也有一定的關係,請自己多加測試,選擇一個權衡值。

 

關閉複合文件格式

調用setUseCompoundFile(false)可以關閉複合文件選項。生成複合文件將消耗更多的時間(經過Lucene-888測試,大概會增加7%-33%的時間)。但是請注意,這樣做將大大的增加搜索和索引使用的文件句柄的數量。如果合併因子也很大的話,你可能會出現用光文件句柄的情況。

 

重用DocumentField實例

lucene 2.3中,新增了一個叫setValue的方法,可以允許你改變字段的值。這樣的好處是你可以在整個索引進程中複用一個Filed實例。這將極大的減少GC負擔。

最好創建一個單一的Document實例,然後添加你想要的字段到文檔中。同時複用添加到文檔的Field實例,通用調用相應的SetValue方法改變相應的字段的值。然後重新將Document添加到索引中。

注意:你不能在一個文檔中多個字段共用一個Field實例,在文檔添加到索引之前,Field的值都不應該改變。也就是說如果你有3個字段,你必須創建3Field實例,然後再之後的Document添加過程中複用它們。

 

在你的分析器Analyzer中使用一個單一的Token實例

在分析器中共享一個單一的token實例也將緩解GC的壓力。

 

Token中使用char[]接口來代替String接口來表示數據

Lucene 2.3中,Token可以使用char數組來表示他的數據。這樣可以避免構建字符串以及GC回收字符串的消耗。通過配合使用單一Token實例和使用char[]接口你可以避免創建新的對象。

 

設置autoCommitfalse

Lucene 2.3中對擁有存儲字段和Term向量的文檔進行了大量的優化,以節省大索引合併的時間。你可以將單一複用的IndexWriter實例的autoCommit設置爲false來見證這些優化帶來的好處。注意這樣做將導致searcherIndexWriter關閉之前不會看到任何索引的更新。如果你認爲這個對你很重要,你可以繼續將autoCommit設置爲true,或者週期性的打開和關閉你的writer

 

如果你要索引很多小文本字段,如果沒有特別需求,建議你將這些小文本字段合併爲一個大的contents字段,然後只索引contents(當然你也可以繼續存儲那些字段)

加大mergeFactor合併因子,但不是越大越好

大的合併因子將延遲segment的合併時間,這樣做可以提高索引速度,因爲合併是索引很耗時的一個部分。但是,這樣做將降低你的搜索速度。同時,你有可能會用光你的文件句柄如果你把合併因子設置的太大。值太大了設置可能降低索引速度,因爲這意味着將同時合併更多的segment,將大大的增加硬盤的負擔。

 

關閉所有你實際上沒有使用的功能

如果你存儲了字段,但是在查詢時根本沒有用到它們,那麼別存儲它們。同樣Term向量也是如此。如果你索引很多的字段,關閉這些字段的不必要的特性將對索引速度提升產生很大的幫助。

 

使用一個更快的分析器

有時間分析文檔將消耗很長的時間。舉例來說,StandardAnalyzer就比較耗時,尤其在Lucene 2.3版本之前。你可以嘗試使用一個更簡單更快但是符合你需求的分析器。

 

加速文檔的構建時間

在通常的情況下,文檔的數據來源可能是外部(比如數據庫,文件系統,蜘蛛從網站上的抓取等),這些通常都比較耗時,儘量優化獲取它們的性能。

 

在你真的需要之前不要隨意的優化optimize索引(只有在需要更快的搜索速度的時候)

在多線程中共享一個IndexWriter

最新的硬件都是適合高併發的(多核CPU,多通道內存構架等),所以使用多線程添加文檔將會帶來不小的性能提升。就算是一臺很老的機器,併發添加文檔都將更好的利用IOCPU。多測試併發的線程數目,獲得一個臨界最優值。

 

將文檔分組在不同的機器上索引然後再合併

如果你有大量的文本文檔需要索引,你可以把你的文檔分爲若干組,在若干臺機器上分別索引不同的組,然後利用writer.addIndexesNoOptimize來將它們合併到最終的一個索引文件中。

 

運行性能測試程序

如果以上的建議都沒有發生效果。建議你運行下性能檢測程序。找出你的程序中哪個部分比較耗時。這通常會給你想不到的驚喜。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章