GITHUB#12370: early-terminate string sort when field is missing from the whole index - #16411
Conversation
…the whole index
When sorting on a string (SortedSet/SortedDoc) field that does not exist
anywhere in the index and the sort has no tie breaker, all documents tie on
the missing value. Once the top-N queue is full, a further missing value can
no longer compete, so the remaining documents should be skipped instead of
fully collected.
TermOrdValComparator only recognized this on the maxOrd side; the ascending
minOrd branch hard-coded minOrd=-1 ("missing still competitive"), which tripped
the guard that disables skipping. Mirror the singleSort recognition onto the
minOrd side, gated on bottomValue==null (a genuine missing value in the queue),
which is stronger than bottomOrd==missingOrd and so does not misfire in the
sort-missing-first mixed-segment case.
Signed-off-by: Serhiy Bzhezytskyy <me@serhiy-bzhezytskyy.com>
|
Are there any objections to its merger? I am ready to resolve them, just let me know. Thanks |
|
It makes sense; I have two slight concerns/questions: (1) we are adding some small cost in a hot spot that usually doesn't help. I assume it's small enough not to worry, but it would be good to domenstrate with benchmarks since this is supposed to be a performance improvement. (2) Can the approach be extended to the case where there is only a single value for every document in the segment (not missing), or the case where all docs in the queue have missing value and we are sorting missing first? |
|
Thanks @serhiy-bzhezytskyy, this looks great! I'd echo @msokolov's request for a benchmark - I don't think it's likely that this is in a hot path, as we already have various checks to ensure that On Mike's second point, this is actually something I've been working on separately and have just opened a PR for: #16424 - currently it only applies to doc-values range queries but I plan on integrating it into TopFieldCollector too. |
|
Ran the benchmark. Short answer: no measurable difference on this hardware — not one task in the suite came in below p=0.05, including the sort tasks themselves. Setup: luceneutil Whole-suite spread was One caveat on how much this is worth: this is a laptop, and a 13.3% median floor can't rule out a small single-digit cost. An earlier run of the same two shas on the same index gave @romseygeek on extending to the single-value and missing-first cases — #16424 looks like it covers that ground properly, and I'd rather not duplicate it. Its only overlap with this PR is |
Closes #12370.
Description
Sorting on a string field that is missing from the whole index currently scans every document instead of early-terminating.
When the sort field doesn't exist anywhere in the segment, every document ties on the "missing" value. With no tie-breaker, once the top-N priority queue is full, all remaining documents are non-competitive and can be skipped — but
TermOrdValComparatordidn't recognize this case, so it visited every doc.Fix
TermOrdValComparatornow mirrors the existingsingleSortcompetitive-iterator recognition to theminOrdpath, gated onbottomValue == null(i.e. the field is missing from the segment). This lets the comparator signal non-competitiveness and skip once the queue is full, exactly as it already does for present fields.Correctness is unchanged — results are identical; this is purely an optimization (so it's filed under Optimizations in CHANGES.txt).
Tests
Added a regression test to
TestSortOptimizationthat asserts early termination happens (non-vacuous — it fails without the fix)../gradlew :lucene:core:test --tests TestSortOptimization→ 29 tests, all green on current main.