LUCENE-10496: avoid unnecessary attempts to evaluate skipping doc if index sort and search sort are in opposite direction (#780)

This commit is contained in:
xiaoping 2022-05-11 17:32:07 +08:00 committed by GitHub
parent 6c6bb00cec
commit e49708e01d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 27 additions and 1 deletions

View File

@ -42,6 +42,10 @@ import org.apache.lucene.util.DocIdSetBuilder;
* but in this case you must override both of these methods.
*/
public abstract class NumericComparator<T extends Number> extends FieldComparator<T> {
// MIN_SKIP_INTERVAL and MAX_SKIP_INTERVAL both should be powers of 2
private static final int MIN_SKIP_INTERVAL = 32;
private static final int MAX_SKIP_INTERVAL = 8192;
protected final T missingValue;
protected final String field;
protected final boolean reverse;
@ -94,6 +98,9 @@ public abstract class NumericComparator<T extends Number> extends FieldComparato
private long iteratorCost = -1;
private int maxDocVisited = -1;
private int updateCounter = 0;
private int currentSkipInterval = MIN_SKIP_INTERVAL;
// helps to be conservative about increasing the sampling interval
private int tryUpdateFailCount = 0;
public NumericLeafComparator(LeafReaderContext context) throws IOException {
this.docValues = getNumericDocValues(context, field);
@ -191,8 +198,9 @@ public abstract class NumericComparator<T extends Number> extends FieldComparato
}
updateCounter++;
// Start sampling if we get called too much
if (updateCounter > 256
&& (updateCounter & 0x1f) != 0x1f) { // Start sampling if we get called too much
&& (updateCounter & (currentSkipInterval - 1)) != currentSkipInterval - 1) {
return;
}
if (reverse == false) {
@ -272,11 +280,29 @@ public abstract class NumericComparator<T extends Number> extends FieldComparato
if (estimatedNumberOfMatches >= threshold) {
// the new range is not selective enough to be worth materializing, it doesn't reduce number
// of docs at least 8x
updateSkipInterval(false);
return;
}
pointValues.intersect(visitor);
competitiveIterator = result.build().iterator();
iteratorCost = competitiveIterator.cost();
updateSkipInterval(true);
}
private void updateSkipInterval(boolean success) {
if (updateCounter > 256) {
if (success) {
currentSkipInterval = Math.max(currentSkipInterval / 2, MIN_SKIP_INTERVAL);
tryUpdateFailCount = 0;
} else {
if (tryUpdateFailCount >= 3) {
currentSkipInterval = Math.min(currentSkipInterval * 2, MAX_SKIP_INTERVAL);
tryUpdateFailCount = 0;
} else {
tryUpdateFailCount++;
}
}
}
}
@Override