Lucene.net:排序时内存不足



我有一个相当大的Lucene.net索引(使用最新版本-2.9创建)。它有大约10亿个文档。它需要大约70GB的高清空间。每个文档都很小,只有两个字段:一个字符串和一个整数。

我想按字符串字段搜索,并按索引字段排序。问题是,当我尝试用排序运行查询时,我会得到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()*(实际用于排序的不同字段数)

我能以某种方式改变这种行为吗?

不,您不能更改此行为。但是,由于您只对顶部结果感兴趣,您可以编写一个自定义的Collector并获得最顶部的结果,而无需对整个结果集进行排序(例如在O(n)时间内的整数数组中查找最大值)

如果您对前n个结果感兴趣,那么您可以使用PriorityQueue。这是我的另一个答案,展示了如何使用PriorityQueueCollector

我最终做了一些不同的事情。意识到我一直希望我的成绩是这样的,我真正需要的是影响得分。在使用Document.SetBoost()时,我使用integer参数的值重建了索引,因此每个文档的分数都由该字段的值决定。由于Lucene的默认行为是返回最好的评分文档,所以我得到了我需要的。

最新更新