2014-02-22 50 views
0

我有一個Lucene索引〜9 Mio.文件,它們使用由幾個TermQueries(其合併爲AND)的BooleanQuery來查詢。非常基本。我的搜索通常會產生大約10個文檔的結果,但在極少數情況下可能會發生,我得到的結果相當多。我在做什麼,是類似如下:Lucene IndexSearcher#search(Query,int),影響參數n

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 
} 

在我偉大的天真,我最初設置MAX_RESULT_COUNTInteger.MAX_VALUE,因爲我想,如果搜索通常只能得到10個結果,最大值也沒有什麼關係而且這個價值永遠不會達到。很大的錯誤。正如我所發現的,搜索的速度更快,我設置的下限爲MAX_RESULT_COUNT

現在,如上所述,我可以設置一個相對較低的值(例如100)來獲得最佳搜索性能。但在一些罕見的情況下,可能會有更多的結果,我也必須抓住。

有人可以向我解釋,爲什麼這個值對搜索速度有如此巨大的影響,雖然實際可用結果的數量是幅度更低?有沒有一種優雅的方式來獲取所有可用的結果,並仍然獲得最高的性能?

回答

1

通過代碼一些快速略讀之後,我發現下面的評論中PriorityQueue的JavaDoc中,並假定我的問題是由數組分配大小爲Integer.MAX_VALUE造成的:

注意:這個類會如果通過預填充設置爲true的構造函數通過PriorityQueue(int,boolean)實例化,則預分配全長maxSize+1

我最終寫了一個自定義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; 
    } 

}