Lucene.net: Недостаточно памяти при сортировке - PullRequest
1 голос
/ 04 марта 2012

У меня довольно большой индекс Lucene.net (создан с последней версией - 2.9).У него ~ 1 миллиард документов.Требуется ~ 70 ГБ пространства HD.Каждый документ очень маленький, всего два поля: строка и целое число.

Я хочу искать по строковому полю и сортировать по полю индекса.Дело в том, что я получаю исключение OutOfMemoryException при попытке выполнить запрос с сортировкой.Код выглядит примерно так:

var sort = new Sort(new SortField("frequency",SortField.INT,false));
var topDocs = searcher.Search(query, null, 1,sort);

Не имеет значения, какой запрос я использую, если я использую сортировку, он падает.Вот трассировка стека:

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at Lucene.Net.Search.FieldCacheImpl.IntCache.CreateValue(IndexReader reader, Entry entryKey)
at Lucene.Net.Search.FieldCacheImpl.Cache.Get(IndexReader reader, Entry key)
at Lucene.Net.Search.FieldCacheImpl.GetInts(IndexReader reader, String field, IntParser parser)
at Lucene.Net.Search.FieldCacheImpl.IntCache.CreateValue(IndexReader reader, Entry entryKey)
at Lucene.Net.Search.FieldCacheImpl.Cache.Get(IndexReader reader, Entry key)
at Lucene.Net.Search.FieldCacheImpl.GetInts(IndexReader reader, String field, IntParser parser)
at Lucene.Net.Search.FieldComparator.IntComparator.SetNextReader(IndexReader reader, Int32 docBase)
at Lucene.Net.Search.IndexSearcher.Search(Weight weight, Filter filter, Collector collector)
at Lucene.Net.Search.IndexSearcher.Search(Weight weight, Filter filter, Int32 nDocs, Sort sort, Boolean fillFields)
at Lucene.Net.Search.IndexSearcher.Search(Weight weight, Filter filter, Int32 nDocs, Sort sort)
at Lucene.Net.Search.Searcher.Search(Query query, Filter filter, Int32 n, Sort sort)

Я довольно новичок в Lucene.Похоже, что он пытается кэшировать огромное количество данных и не хватает памяти.

Обновление: действительно, похоже, что Lucene пытается создать массив int [maxDoc], который в моем случае огромен.

Сортировка использует кэши значений терминов, поддерживаемых внутренним HitQueue(ы).Кэш является статическим и содержит целочисленный или плавающий массив длины IndexReader.maxDoc () для каждого имени поля, для которого выполняется сортировка.Другими словами, размер кэша в байтах: 4 * IndexReader.maxDoc () * (число различных полей, фактически используемых для сортировки)

Можно ли как-то изменить это поведение?

Ответы [ 2 ]

1 голос
/ 05 марта 2012

Я закончил тем, что делал что-то другое.Понимая, что я всегда хочу, чтобы мой результат сортировался таким образом, мне действительно нужно повлиять на Оценка .Я перестроил свой индекс при использовании Document.SetBoost () со значением целочисленного параметра, поэтому в оценке каждого документа преобладает значение этого поля.Поскольку стандартное поведение Lucene - возвращать лучшие документы для оценки, я получил то, что мне было нужно.

1 голос
/ 05 марта 2012

Нет, вы не можете изменить это поведение. Но так как вас интересует только верхний результат, вы можете написать пользовательский Collector и получить самый верхний результат без сортировки всего набора результатов (например, поиск максимума в целочисленном массиве за O (n) раз)

Если вас интересуют топ-n результатов, вы можете использовать PriorityQueue. Вот мой другой ответ , показывающий, как использовать PriorityQueue и Collector

...