mirror of https://github.com/apache/lucene.git
Early exit range queries on non-matching segments. (#13033)
This change makes `PointRangeQuery` exit early when it knows that it doesn't match a segment. In the case when this query is part of a conjunction, this helps make sure `ScorerSupplier#get` doesn't get called on other required clauses, which is sometimes an expensive operation (e.g. multi-term queries). This is especially relevant for time-based data combined with `LogByteSizePolicy`, which gives non-adjacent ranges of timestamps to each segment, which in-turn increases the likelihood that some segments won't match a range query at all.
This commit is contained in:
parent
fb5037f841
commit
082d318abd
|
@ -216,6 +216,11 @@ Optimizations
|
||||||
|
|
||||||
* GITHUB#12989: Split taxonomy facet arrays across reusable chunks of elements to reduce allocations. (Michael Froh, Stefan Vodita)
|
* GITHUB#12989: Split taxonomy facet arrays across reusable chunks of elements to reduce allocations. (Michael Froh, Stefan Vodita)
|
||||||
|
|
||||||
|
* GITHUB#13033: PointRangeQuery now exits earlier on segments whose values
|
||||||
|
don't intersect with the query range. When a PointRangeQuery is a required
|
||||||
|
clause of a boolean query, this helps save work on other required clauses of
|
||||||
|
the same boolean query. (Adrien Grand)
|
||||||
|
|
||||||
Bug Fixes
|
Bug Fixes
|
||||||
---------------------
|
---------------------
|
||||||
* GITHUB#12866: Prevent extra similarity computation for single-level HNSW graphs. (Kaival Parikh)
|
* GITHUB#12866: Prevent extra similarity computation for single-level HNSW graphs. (Kaival Parikh)
|
||||||
|
|
|
@ -290,6 +290,24 @@ public abstract class PointRangeQuery extends Query {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (values.getDocCount() == 0) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
final byte[] fieldPackedLower = values.getMinPackedValue();
|
||||||
|
final byte[] fieldPackedUpper = values.getMaxPackedValue();
|
||||||
|
for (int i = 0; i < numDims; ++i) {
|
||||||
|
int offset = i * bytesPerDim;
|
||||||
|
if (comparator.compare(lowerPoint, offset, fieldPackedUpper, offset) > 0
|
||||||
|
|| comparator.compare(upperPoint, offset, fieldPackedLower, offset) < 0) {
|
||||||
|
// If this query is a required clause of a boolean query, then returning null here
|
||||||
|
// will help make sure that we don't call ScorerSupplier#get on other required clauses
|
||||||
|
// of the same boolean query, which is an expensive operation for some queries (e.g.
|
||||||
|
// multi-term queries).
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boolean allDocsMatch;
|
boolean allDocsMatch;
|
||||||
if (values.getDocCount() == reader.maxDoc()) {
|
if (values.getDocCount() == reader.maxDoc()) {
|
||||||
final byte[] fieldPackedLower = values.getMinPackedValue();
|
final byte[] fieldPackedLower = values.getMinPackedValue();
|
||||||
|
|
|
@ -2454,4 +2454,37 @@ public class TestPointQueries extends LuceneTestCase {
|
||||||
r.close();
|
r.close();
|
||||||
dir.close();
|
dir.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testRangeQuerySkipsNonMatchingSegments() throws IOException {
|
||||||
|
Directory dir = newDirectory();
|
||||||
|
IndexWriter w = new IndexWriter(dir, newIndexWriterConfig());
|
||||||
|
Document doc = new Document();
|
||||||
|
doc.add(new IntPoint("field", 2));
|
||||||
|
doc.add(new IntPoint("field2d", 1, 3));
|
||||||
|
w.addDocument(doc);
|
||||||
|
|
||||||
|
DirectoryReader reader = DirectoryReader.open(w);
|
||||||
|
IndexSearcher searcher = newSearcher(reader);
|
||||||
|
|
||||||
|
Query query = IntPoint.newRangeQuery("field", 0, 1);
|
||||||
|
Weight weight =
|
||||||
|
searcher.createWeight(searcher.rewrite(query), ScoreMode.COMPLETE_NO_SCORES, 1f);
|
||||||
|
assertNull(weight.scorerSupplier(reader.leaves().get(0)));
|
||||||
|
|
||||||
|
query = IntPoint.newRangeQuery("field", 3, 4);
|
||||||
|
weight = searcher.createWeight(searcher.rewrite(query), ScoreMode.COMPLETE_NO_SCORES, 1f);
|
||||||
|
assertNull(weight.scorerSupplier(reader.leaves().get(0)));
|
||||||
|
|
||||||
|
query = IntPoint.newRangeQuery("field2d", new int[] {0, 0}, new int[] {2, 2});
|
||||||
|
weight = searcher.createWeight(searcher.rewrite(query), ScoreMode.COMPLETE_NO_SCORES, 1f);
|
||||||
|
assertNull(weight.scorerSupplier(reader.leaves().get(0)));
|
||||||
|
|
||||||
|
query = IntPoint.newRangeQuery("field2d", new int[] {2, 2}, new int[] {4, 4});
|
||||||
|
weight = searcher.createWeight(searcher.rewrite(query), ScoreMode.COMPLETE_NO_SCORES, 1f);
|
||||||
|
assertNull(weight.scorerSupplier(reader.leaves().get(0)));
|
||||||
|
|
||||||
|
reader.close();
|
||||||
|
w.close();
|
||||||
|
dir.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue