影响Lucene索引速度原因以及提高索引速度技巧
在網(wǎng)上看了一篇外文文章,里面介紹了提高Lucene索引速度的技巧,分享給大家。
先來(lái)看下影響索引的主要因素:
MaxMergeDocs
該參數(shù)決定寫(xiě)入內(nèi)存索引文檔個(gè)數(shù),到達(dá)該數(shù)目后就把該內(nèi)存索引寫(xiě)入硬盤(pán),生成一個(gè)新的索引segment文件。
所以該參數(shù)也就是一個(gè)內(nèi)存buffer,一般來(lái)說(shuō)越大索引速度越快。
MaxBufferedDocs這個(gè)參數(shù)默認(rèn)是disabled的,因?yàn)長(zhǎng)ucene中還用另外一個(gè)參數(shù)(RAMBufferSizeMB)控制這個(gè)bufffer的索引文檔個(gè)數(shù)。
其實(shí)MaxBufferedDocs和RAMBufferSizeMB這兩個(gè)參數(shù)是可以一起使用的,一起使用時(shí)只要有一個(gè)觸發(fā)條件滿足就寫(xiě)入硬盤(pán),生成一個(gè)新的索引segment文件。
RAMBufferSizeMB
控制用于buffer索引文檔的內(nèi)存上限,如果buffer的索引文檔個(gè)數(shù)到達(dá)該上限就寫(xiě)入硬盤(pán)。當(dāng)然,一般來(lái)說(shuō)也只越大索引速度越快。
當(dāng)我們對(duì)文檔大小不太確定時(shí),這個(gè)參數(shù)就相當(dāng)有用,不至于outofmemory error.
MergeFactor
這個(gè)參數(shù)是用于子索引(Segment)合并的。
Lucene中索引總體上是這樣進(jìn)行,索引現(xiàn)寫(xiě)到內(nèi)存,觸發(fā)一定限制條件后寫(xiě)入硬盤(pán),生成一個(gè)獨(dú)立的子索引-lucene中叫Segment。一般來(lái)說(shuō)這些子索引需要合并成一個(gè)索引,也就是optimize(),否則會(huì)影響檢索速度,而且也可能導(dǎo)致open too many files。
MergeFactor 這個(gè)參數(shù)就是控制當(dāng)硬盤(pán)中有多少個(gè)子索引segments,我們就需要現(xiàn)把這些索引合并沖一個(gè)稍微大些的索引了。
MergeFactor這個(gè)不能設(shè)置太大,特別是當(dāng)MaxBufferedDocs比較小時(shí)(segment 越多),否則會(huì)導(dǎo)致open too many files錯(cuò)誤,甚至導(dǎo)致虛擬機(jī)外面出錯(cuò)。
Note: Lucene 中默認(rèn)索引合并機(jī)制并不是兩兩合并,好像是多個(gè)segment 合并成最終的一個(gè)大索引,所以MergeFactor越大耗費(fèi)內(nèi)存越多,索引速度也會(huì)快些,但我的感覺(jué)太大譬如300,最后合并的時(shí)候還是很滿。Batch indexing 應(yīng) MergeFactor>10
21世紀(jì)開(kāi)運(yùn)網(wǎng)星座紫微斗數(shù)在線排盤(pán)加快索引的一些技巧:
? 確認(rèn)你在使用最新的Lucene版本。
? 盡量使用本地文件系統(tǒng)
遠(yuǎn)程文件系統(tǒng)一般來(lái)說(shuō)都會(huì)降低索引速度。如果索引必須分布在遠(yuǎn)程服務(wù)器,請(qǐng)嘗試先在本地生成索引,然后分發(fā)到遠(yuǎn)程服務(wù)器上。
? 使用更快的硬件設(shè)備,特別是更快的IO設(shè)備
? 在索引期間復(fù)用單一的IndexWriter實(shí)例
? 使用按照內(nèi)存消耗Flush代替根據(jù)文檔數(shù)量Flush
在Lucene 2.2之前的版本,可以在每次添加文檔后調(diào)用ramSizeInBytes方法,當(dāng)索引消耗過(guò)多的內(nèi)存時(shí),然后在調(diào)用flush()方法。這樣做在索引大量小文檔或者文檔大小不定的情況下尤為有效。你必須先把maxBufferedDocs參數(shù)設(shè)置足夠大,以防止writer基于文檔數(shù)量flush。但是注意,別把這個(gè)值設(shè)置的太大,否則你將遭遇Lucene-845號(hào)BUG。不過(guò)這個(gè)BUG已經(jīng)在2.3版本中得到解決。
在Lucene2.3之后的版本。IndexWriter可以自動(dòng)的根據(jù)內(nèi)存消耗調(diào)用flush()。你可以通過(guò)writer.setRAMBufferSizeMB()來(lái)設(shè)置緩存大小。當(dāng)你打算按照內(nèi)存大小flush后,確保沒(méi)有在別的地方設(shè)置MaxBufferedDocs值。否則flush條件將變的不確定(誰(shuí)先符合條件就按照誰(shuí))。
? 在你能承受的范圍內(nèi)使用更多的內(nèi)存
在flush前使用更多的內(nèi)存意味著Lucene將在索引時(shí)生成更大的segment,也意味著合并次數(shù)也隨之減少。在Lucene-843中測(cè)試,大概48MB內(nèi)存可能是一個(gè)比較合適的值。但是,你的程序可能會(huì)是另外一個(gè)值。這跟不同的機(jī)器也有一定的關(guān)系,請(qǐng)自己多加測(cè)試,選擇一個(gè)權(quán)衡值。
? 關(guān)閉復(fù)合文件格式
調(diào)用setUseCompoundFile(false)可以關(guān)閉復(fù)合文件選項(xiàng)。生成復(fù)合文件將消耗更多的時(shí)間(經(jīng)過(guò)Lucene-888測(cè)試,大概會(huì)增加7%-33%的時(shí)間)。但是請(qǐng)注意,這樣做將大大的增加搜索和索引使用的文件句柄的數(shù)量。如果合并因子也很大的話,你可能會(huì)出現(xiàn)用光文件句柄的情況。
? 重用Document和Field實(shí)例
在lucene 2.3中,新增了一個(gè)叫setValue的方法,可以允許你改變字段的值。這樣的好處是你可以在整個(gè)索引進(jìn)程中復(fù)用一個(gè)Filed實(shí)例。這將極大的減少GC負(fù)擔(dān)。
最好創(chuàng)建一個(gè)單一的Document實(shí)例,然后添加你想要的字段到文檔中。同時(shí)復(fù)用添加到文檔的Field實(shí)例,通用調(diào)用相應(yīng)的SetValue方法改變相應(yīng)的字段的值。然后重新將Document添加到索引中。
注意:你不能在一個(gè)文檔中多個(gè)字段共用一個(gè)Field實(shí)例,在文檔添加到索引之前,Field的值都不應(yīng)該改變。也就是說(shuō)如果你有3個(gè)字段,你必須創(chuàng)建3個(gè)Field實(shí)例,然后再之后的Document添加過(guò)程中復(fù)用它們。
? 在你的分析器Analyzer中使用一個(gè)單一的Token實(shí)例
在分析器中共享一個(gè)單一的token實(shí)例也將緩解GC的壓力。
? 在Token中使用char[]接口來(lái)代替String接口來(lái)表示數(shù)據(jù)
在Lucene 2.3中,Token可以使用char數(shù)組來(lái)表示他的數(shù)據(jù)。這樣可以避免構(gòu)建字符串以及GC回收字符串的消耗。通過(guò)配合使用單一Token實(shí)例和使用char[]接口你可以避免創(chuàng)建新的對(duì)象。
? 設(shè)置autoCommit為false
在Lucene 2.3中對(duì)擁有存儲(chǔ)字段和Term向量的文檔進(jìn)行了大量的優(yōu)化,以節(jié)省大索引合并的時(shí)間。你可以將單一復(fù)用的IndexWriter實(shí)例的autoCommit設(shè)置為false來(lái)見(jiàn)證這些優(yōu)化帶來(lái)的好處。注意這樣做將導(dǎo)致searcher在IndexWriter關(guān)閉之前不會(huì)看到任何索引的更新。如果你認(rèn)為這個(gè)對(duì)你很重要,你可以繼續(xù)將autoCommit設(shè)置為true,或者周期性的打開(kāi)和關(guān)閉你的writer。
? 如果你要索引很多小文本字段,如果沒(méi)有特別需求,建議你將這些小文本字段合并為一個(gè)大的contents字段,然后只索引contents。(當(dāng)然你也可以繼續(xù)存儲(chǔ)那些字段)
? 加大mergeFactor合并因子,但不是越大越好
大的合并因子將延遲segment的合并時(shí)間,這樣做可以提高索引速度,因?yàn)楹喜⑹撬饕芎臅r(shí)的一個(gè)部分。但是,這樣做將降低你的搜索速度。同時(shí),你有可能會(huì)用光你的文件句柄如果你把合并因子設(shè)置的太大。值太大了設(shè)置可能降低索引速度,因?yàn)檫@意味著將同時(shí)合并更多的segment,將大大的增加硬盤(pán)的負(fù)擔(dān)。
? 關(guān)閉所有你實(shí)際上沒(méi)有使用的功能
如果你存儲(chǔ)了字段,但是在查詢時(shí)根本沒(méi)有用到它們,那么別存儲(chǔ)它們。同樣Term向量也是如此。如果你索引很多的字段,關(guān)閉這些字段的不必要的特性將對(duì)索引速度提升產(chǎn)生很大的幫助。
? 使用一個(gè)更快的分析器
有時(shí)間分析文檔將消耗很長(zhǎng)的時(shí)間。舉例來(lái)說(shuō),StandardAnalyzer就比較耗時(shí),尤其在Lucene 2.3版本之前。你可以嘗試使用一個(gè)更簡(jiǎn)單更快但是符合你需求的分析器。
? 加速文檔的構(gòu)建時(shí)間
在通常的情況下,文檔的數(shù)據(jù)來(lái)源可能是外部(比如數(shù)據(jù)庫(kù),文件系統(tǒng),蜘蛛從網(wǎng)站上的抓取等),這些通常都比較耗時(shí),盡量?jī)?yōu)化獲取它們的性能。
? 在你真的需要之前不要隨意的優(yōu)化optimize索引(只有在需要更快的搜索速度的時(shí)候)
? 在多線程中共享一個(gè)IndexWriter
最新的硬件都是適合高并發(fā)的(多核CPU,多通道內(nèi)存構(gòu)架等),所以使用多線程添加文檔將會(huì)帶來(lái)不小的性能提升。就算是一臺(tái)很老的機(jī)器,并發(fā)添加文檔都將更好的利用IO和CPU。多測(cè)試并發(fā)的線程數(shù)目,獲得一個(gè)臨界最優(yōu)值。
? 將文檔分組在不同的機(jī)器上索引然后再合并
如果你有大量的文本文檔需要索引,你可以把你的文檔分為若干組,在若干臺(tái)機(jī)器上分別索引不同的組,然后利用writer.addIndexesNoOptimize來(lái)將它們合并到最終的一個(gè)索引文件中。
? 運(yùn)行性能測(cè)試程序
如果以上的建議都沒(méi)有發(fā)生效果。建議你運(yùn)行下性能檢測(cè)程序。找出你的程序中哪個(gè)部分比較耗時(shí)。這通常會(huì)給你想不到的驚喜。
本翻譯屬于原創(chuàng),轉(zhuǎn)載時(shí)請(qǐng)注明出處,英文原版請(qǐng)查看:
http://wiki.apache.org/jakarta-lucene/ImproveIndexingSpeed
?
http://www.21kaiyun.com
?
總結(jié)
以上是生活随笔為你收集整理的影响Lucene索引速度原因以及提高索引速度技巧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 黄豆焖猪蹄(高压锅)怎么做
- 下一篇: Memcached 缓存系统的-介绍、安