Я пытаюсь проиндексировать около 10.000.000 документов с помощью Lucene.NET 2.9.2. Эти документы (сообщения на форуме разной длины) берутся большими партиями по 10.000 из базы данных MSSQL, а затем передаются в мой класс-оболочку Lucene.NET с именем LuceneCorpus:
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();
}
}
Теперь моя проблема заключается в том, что потребление памяти постоянно заполняется, пока я, наконец, не достигну исключения из-за нехватки памяти после индексации около 700 000 документов где-нибудь в методе IndexPosts.
Насколько я знаю, средство записи индекса должно сбрасываться, когда оно достигает либо RAMBufferSize (128 МБ), либо при вызове Commit (). На самом деле, писатель определенно делает сброс и даже отслеживает приливы, но память все равно продолжает заполняться. Писатель как-то хранит ссылку на документы, чтобы они не были собраны в мусор, или что мне здесь не хватает?
Заранее спасибо!
Редактировать: Я также попытался инициализировать Writer, Analyzer и indexDir в области действия метода AddPosts вместо общеклассного, но это также не предотвращает исключение OOM.