Index: lucene/CHANGES.txt =================================================================== --- lucene/CHANGES.txt (revision 963233) +++ lucene/CHANGES.txt (working copy) @@ -716,6 +716,9 @@ files when a mergedSegmentWarmer is set on IndexWriter. (Mike McCandless) +* LUCENE-2130: Fix performance issue when FuzzyQuery runs on a + multi-segment index (Michael McCandless) + API Changes * LUCENE-2281: added doBeforeFlush to IndexWriter to allow extensions to perform Index: lucene/src/test/org/apache/lucene/index/TestMultiFields.java =================================================================== --- lucene/src/test/org/apache/lucene/index/TestMultiFields.java (revision 963233) +++ lucene/src/test/org/apache/lucene/index/TestMultiFields.java (working copy) @@ -88,6 +88,8 @@ BytesRef term = terms.get(r.nextInt(terms.size())); DocsEnum docsEnum = terms2.docs(delDocs, term, null); + assertNotNull(docsEnum); + int count = 0; for(int docID : docs.get(term)) { if (!deleted.contains(docID)) { Index: lucene/src/java/org/apache/lucene/index/MultiTermsEnum.java =================================================================== --- lucene/src/java/org/apache/lucene/index/MultiTermsEnum.java (revision 963233) +++ lucene/src/java/org/apache/lucene/index/MultiTermsEnum.java (working copy) @@ -42,6 +42,9 @@ private final MultiDocsEnum.EnumWithSlice[] subDocs; private final MultiDocsAndPositionsEnum.EnumWithSlice[] subDocsAndPositions; + private BytesRef lastSeek; + private final BytesRef lastSeekScratch = new BytesRef(); + private int numTop; private int numSubs; private BytesRef current; @@ -139,8 +142,40 @@ public SeekStatus seek(BytesRef term, boolean useCache) throws IOException { queue.clear(); numTop = 0; + + boolean seekOpt = false; + if (lastSeek != null && termComp.compare(lastSeek, term) <= 0) { + seekOpt = true; + } + lastSeekScratch.copy(term); + lastSeek = lastSeekScratch; + for(int i=0;i