我想用Lucene.NET 2.9.2來索引大約10.000.000個文檔。這些文件(長度不同的論壇帖子)是從MSSQL數據庫採取10.000散貨,然後傳遞給我的Lucene.NET包裝類稱爲LuceneCorpus:Lucene.Net 2.9.2:添加多個文檔時出現OOM異常
public static void IndexPosts(LuceneCorpus luceneCorpus, IPostsRepository postsRepository, int chunkSize)
{
// omitted: this whole method is executed in a background worker to enable GUI feedback
// chunkSize is 10.000
int count = 0;
// totalSteps is ~10.000.000
int totalSteps = postsRepository.All.Count();
while (true)
{
var posts = postsRepository.All.Skip(count).Take(chunkSize).ToList();
if (posts.Count == 0)
break;
luceneCorpus.AddPosts(posts);
count += posts.Count;
}
luceneCorpus.OptimizeIndex();
}
我讀了推薦使用單一的IndexWriter而不是爲每一批文件打開和關閉一個新文件。因此,我LuceneCorpus類看起來是這樣的:
public class LuceneCorpus
{
private Analyzer _analyzer;
private Directory _indexDir;
private IndexWriter _writer;
public LuceneCorpus(DirectoryInfo indexDirectory)
{
_indexDir = FSDirectory.Open(indexDirectory);
_analyzer = new StandardAnalyzer(Version.LUCENE_29);
_writer = new IndexWriter(_indexDir, _analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED);
_writer.SetRAMBufferSizeMB(128);
}
public void AddPosts(IEnumerable<Post> posts)
{
List<Document> docs = new List<Document>();
foreach (var post in posts)
{
var doc = new Document();
doc.Add(new Field("SimplifiedBody", post.SimplifiedBody, Field.Store.NO, Field.Index.ANALYZED));
_writer.AddDocument(doc);
}
_writer.Commit();
}
public void OptimizeIndex()
{
_writer.Optimize();
}
}
現在,我的問題是,內存消耗不斷在IndexPosts方法填補,直到我終於到達索引之後的內存不足的異常約700.000文件的某處。
據我所知,索引寫入器應該在達到RAMBufferSize(128 MB)或調用Commit()時進行刷新。事實上,作家肯定會沖洗甚至跟蹤沖洗,但記憶仍在不斷填滿。作者是否保持對文件的引用,以便它們不被垃圾收集或我在這裏錯過了什麼?
在此先感謝!
編輯:我也試着在AddPosts方法的範圍內初始化writer,analyzer和indexDir,而不是class-wide,但是也不能阻止OOM異常。
這將是一般的罰款,但即使我使用批處理作家的方法出現問題。我嘗試過使用不同的批量(500,1000或10000個文檔),但內存仍然不斷填滿(!),直到內存不足。 – Shackles
供參考:現在Lucene無關的內存泄漏已經修復,我甚至可以使用單一的寫入器方法! – Shackles