我有一个约9百万的Lucene索引。在文档中,使用BooleanQuery
查询它们,TermQueries
由多个AND
组合而成(TopDocs searchResult = searcher.search(query, MAX_RESULT_COUNT);
for (int i = 0; i < searchResult.scoreDocs.length; i++) {
Document document = searcher.doc(searchResult.scoreDocs[i].doc);
// read data from index fields and create result instances here
}
组合在一起)。非常基本的。我的搜索通常会产生大约10个文档的结果,但在极少数情况下可能会发生,我得到的结果要多得多。我正在做的事情如下:
MAX_RESULT_COUNT
我非常天真,我最初将Integer.MAX_VALUE
设置为MAX_RESULT_COUNT
,因为我认为,如果搜索通常只获得10个结果,则最大值无关紧要,无论如何都不会达到该值。很大的错误。正如我发现的那样,搜索的幅度更快,我设置的{{1}}越低。
现在,如上所述,我可以设置相对较低的值(例如100)以获得最佳搜索性能。但在极少数情况下,可能会有更多结果,我也必须抓住这些结果。
有人可以向我解释一下,为什么这个值会对搜索速度产生如此大的影响,虽然实际可用结果的数量是多少?是否有一种优雅的方式来获取所有可用的结果并仍然获得最高性能?
答案 0 :(得分:2)
在快速浏览代码之后,我在PriorityQueue
的JavaDocs中找到了以下注释,并假设我的问题是由大小为Integer.MAX_VALUE
的数组分配引起的:
注意:如果通过
maxSize+1
构造函数实例化,并且预填充设置为PriorityQueue(int,boolean)
,则此类将预先分配一个长度为true
的完整数组。
我最后写了一个自定义Collector
。因为我不需要评分和文件顺序在我的情况下是无关紧要的,这很简单:
private static final class SimpleCollector extends Collector {
final Set<Integer> docs = CollectionHelper.newHashSet();
int docBase;
@Override
public void setScorer(Scorer scorer) throws IOException {
// no scoring
}
@Override
public void collect(int doc) throws IOException {
docs.add(docBase + doc);
}
@Override
public void setNextReader(AtomicReaderContext context) throws IOException {
this.docBase = context.docBase;
}
@Override
public boolean acceptsDocsOutOfOrder() {
return true;
}
}