Lucene.Net 2.9.2:添加许多文档时的OOM异常

时间:2011-08-28 11:43:15

标签: indexing lucene.net out-of-memory

我正在尝试使用Lucene.NET 2.9.2索引大约10.000.000个文档。这些文档(不同长度的论坛帖子)从MSSQL数据库中以10.000的大小获取,然后传递给名为LuceneCorpus的Lucene.NET包装类:

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而不是为每个文档大小打开和关闭一个新的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,而不是在类范围内,但这也不会阻止OOM异常。

3 个答案:

答案 0 :(得分:1)

尝试最新且最棒的。它有一些内存泄漏修复。

https://svn.apache.org/repos/asf/incubator/lucene.net/branches/Lucene.Net_2_9_4g/src/

答案 1 :(得分:0)

  

我读过建议使用单个IndexWriter而不是   为每批文件打开和关闭一个新文件。

总的来说这可能是真的,但是你的特殊情况似乎需要另一种方法。你应该每批尝试一个作家。您的大内存需求迫使您使用不太理想的效率解决方案。交易记忆的速度和反之亦然 - 这很常见。

答案 2 :(得分:0)

显然Lucene没有导致内存泄漏,但我的PostsRepository的DataContext是。我通过为每个“Take”迭代使用临时非跟踪DC来解决它。

对不起,谢谢!