Sort document by internal doc id in FetchPhase to better use LRU cache (#57273)
This change sorts the docIdsToLoad once instead of in each sub-phase.
This commit is contained in:
parent
ab65a57d70
commit
8c93f4e154
|
@ -61,6 +61,7 @@ import org.elasticsearch.search.lookup.SourceLookup;
|
||||||
import org.elasticsearch.tasks.TaskCancelledException;
|
import org.elasticsearch.tasks.TaskCancelledException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -144,13 +145,20 @@ public class FetchPhase implements SearchPhase {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
DocIdToIndex[] docs = new DocIdToIndex[context.docIdsToLoadSize()];
|
||||||
|
for (int index = 0; index < context.docIdsToLoadSize(); index++) {
|
||||||
|
docs[index] = new DocIdToIndex(context.docIdsToLoad()[context.docIdsToLoadFrom() + index], index);
|
||||||
|
}
|
||||||
|
Arrays.sort(docs);
|
||||||
|
|
||||||
SearchHit[] hits = new SearchHit[context.docIdsToLoadSize()];
|
SearchHit[] hits = new SearchHit[context.docIdsToLoadSize()];
|
||||||
|
SearchHit[] sortedHits = new SearchHit[context.docIdsToLoadSize()];
|
||||||
FetchSubPhase.HitContext hitContext = new FetchSubPhase.HitContext();
|
FetchSubPhase.HitContext hitContext = new FetchSubPhase.HitContext();
|
||||||
for (int index = 0; index < context.docIdsToLoadSize(); index++) {
|
for (int index = 0; index < context.docIdsToLoadSize(); index++) {
|
||||||
if (context.isCancelled()) {
|
if (context.isCancelled()) {
|
||||||
throw new TaskCancelledException("cancelled");
|
throw new TaskCancelledException("cancelled");
|
||||||
}
|
}
|
||||||
int docId = context.docIdsToLoad()[context.docIdsToLoadFrom() + index];
|
int docId = docs[index].docId;
|
||||||
int readerIndex = ReaderUtil.subIndex(docId, context.searcher().getIndexReader().leaves());
|
int readerIndex = ReaderUtil.subIndex(docId, context.searcher().getIndexReader().leaves());
|
||||||
LeafReaderContext subReaderContext = context.searcher().getIndexReader().leaves().get(readerIndex);
|
LeafReaderContext subReaderContext = context.searcher().getIndexReader().leaves().get(readerIndex);
|
||||||
int subDocId = docId - subReaderContext.docBase;
|
int subDocId = docId - subReaderContext.docBase;
|
||||||
|
@ -165,7 +173,8 @@ public class FetchPhase implements SearchPhase {
|
||||||
storedToRequestedFields, subReaderContext);
|
storedToRequestedFields, subReaderContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
hits[index] = searchHit;
|
sortedHits[index] = searchHit;
|
||||||
|
hits[docs[index].index] = searchHit;
|
||||||
hitContext.reset(searchHit, subReaderContext, subDocId, context.searcher());
|
hitContext.reset(searchHit, subReaderContext, subDocId, context.searcher());
|
||||||
for (FetchSubPhase fetchSubPhase : fetchSubPhases) {
|
for (FetchSubPhase fetchSubPhase : fetchSubPhases) {
|
||||||
fetchSubPhase.hitExecute(context, hitContext);
|
fetchSubPhase.hitExecute(context, hitContext);
|
||||||
|
@ -176,7 +185,7 @@ public class FetchPhase implements SearchPhase {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (FetchSubPhase fetchSubPhase : fetchSubPhases) {
|
for (FetchSubPhase fetchSubPhase : fetchSubPhases) {
|
||||||
fetchSubPhase.hitsExecute(context, hits);
|
fetchSubPhase.hitsExecute(context, sortedHits);
|
||||||
if (context.isCancelled()) {
|
if (context.isCancelled()) {
|
||||||
throw new TaskCancelledException("cancelled");
|
throw new TaskCancelledException("cancelled");
|
||||||
}
|
}
|
||||||
|
@ -189,6 +198,21 @@ public class FetchPhase implements SearchPhase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class DocIdToIndex implements Comparable<DocIdToIndex> {
|
||||||
|
final int docId;
|
||||||
|
final int index;
|
||||||
|
|
||||||
|
DocIdToIndex(int docId, int index) {
|
||||||
|
this.docId = docId;
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(DocIdToIndex o) {
|
||||||
|
return Integer.compare(docId, o.docId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int findRootDocumentIfNested(SearchContext context, LeafReaderContext subReaderContext, int subDocId) throws IOException {
|
private int findRootDocumentIfNested(SearchContext context, LeafReaderContext subReaderContext, int subDocId) throws IOException {
|
||||||
if (context.mapperService().hasNested()) {
|
if (context.mapperService().hasNested()) {
|
||||||
BitSet bits = context.bitsetFilterCache()
|
BitSet bits = context.bitsetFilterCache()
|
||||||
|
|
|
@ -81,6 +81,8 @@ public interface FetchSubPhase {
|
||||||
*/
|
*/
|
||||||
default void hitExecute(SearchContext context, HitContext hitContext) throws IOException {}
|
default void hitExecute(SearchContext context, HitContext hitContext) throws IOException {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the hits level phase (note, hits are sorted by doc ids).
|
||||||
|
*/
|
||||||
default void hitsExecute(SearchContext context, SearchHit[] hits) throws IOException {}
|
default void hitsExecute(SearchContext context, SearchHit[] hits) throws IOException {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,7 @@ import org.elasticsearch.search.internal.SearchContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ -78,9 +76,6 @@ public final class FetchDocValuesPhase implements FetchSubPhase {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hits = hits.clone(); // don't modify the incoming hits
|
|
||||||
Arrays.sort(hits, Comparator.comparingInt(SearchHit::docId));
|
|
||||||
|
|
||||||
if (context.docValuesContext().fields().stream()
|
if (context.docValuesContext().fields().stream()
|
||||||
.map(f -> f.format)
|
.map(f -> f.format)
|
||||||
.filter(USE_DEFAULT_FORMAT::equals)
|
.filter(USE_DEFAULT_FORMAT::equals)
|
||||||
|
|
|
@ -30,8 +30,6 @@ import org.elasticsearch.search.fetch.FetchSubPhase;
|
||||||
import org.elasticsearch.search.internal.SearchContext;
|
import org.elasticsearch.search.internal.SearchContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
public class FetchScorePhase implements FetchSubPhase {
|
public class FetchScorePhase implements FetchSubPhase {
|
||||||
|
@ -44,9 +42,6 @@ public class FetchScorePhase implements FetchSubPhase {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hits = hits.clone(); // don't modify the incoming hits
|
|
||||||
Arrays.sort(hits, Comparator.comparingInt(SearchHit::docId));
|
|
||||||
|
|
||||||
final IndexSearcher searcher = context.searcher();
|
final IndexSearcher searcher = context.searcher();
|
||||||
final Weight weight = searcher.createWeight(searcher.rewrite(context.query()), ScoreMode.COMPLETE, 1);
|
final Weight weight = searcher.createWeight(searcher.rewrite(context.query()), ScoreMode.COMPLETE, 1);
|
||||||
Iterator<LeafReaderContext> leafContextIterator = searcher.getIndexReader().leaves().iterator();
|
Iterator<LeafReaderContext> leafContextIterator = searcher.getIndexReader().leaves().iterator();
|
||||||
|
|
|
@ -28,8 +28,6 @@ import org.elasticsearch.search.fetch.FetchSubPhase;
|
||||||
import org.elasticsearch.search.internal.SearchContext;
|
import org.elasticsearch.search.internal.SearchContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
public final class FetchVersionPhase implements FetchSubPhase {
|
public final class FetchVersionPhase implements FetchSubPhase {
|
||||||
@Override
|
@Override
|
||||||
|
@ -39,9 +37,6 @@ public final class FetchVersionPhase implements FetchSubPhase {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hits = hits.clone(); // don't modify the incoming hits
|
|
||||||
Arrays.sort(hits, Comparator.comparingInt(SearchHit::docId));
|
|
||||||
|
|
||||||
int lastReaderId = -1;
|
int lastReaderId = -1;
|
||||||
NumericDocValues versions = null;
|
NumericDocValues versions = null;
|
||||||
for (SearchHit hit : hits) {
|
for (SearchHit hit : hits) {
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.elasticsearch.search.internal.SearchContext.Lifetime;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -49,8 +48,6 @@ public final class MatchedQueriesPhase implements FetchSubPhase {
|
||||||
context.parsedQuery() == null) {
|
context.parsedQuery() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hits = hits.clone(); // don't modify the incoming hits
|
|
||||||
Arrays.sort(hits, (a, b) -> Integer.compare(a.docId(), b.docId()));
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<String>[] matchedQueries = new List[hits.length];
|
List<String>[] matchedQueries = new List[hits.length];
|
||||||
for (int i = 0; i < matchedQueries.length; ++i) {
|
for (int i = 0; i < matchedQueries.length; ++i) {
|
||||||
|
|
|
@ -30,10 +30,8 @@ import org.elasticsearch.search.internal.SearchContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public final class ScriptFieldsPhase implements FetchSubPhase {
|
public final class ScriptFieldsPhase implements FetchSubPhase {
|
||||||
|
@ -44,9 +42,6 @@ public final class ScriptFieldsPhase implements FetchSubPhase {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hits = hits.clone(); // don't modify the incoming hits
|
|
||||||
Arrays.sort(hits, Comparator.comparingInt(SearchHit::docId));
|
|
||||||
|
|
||||||
int lastReaderId = -1;
|
int lastReaderId = -1;
|
||||||
FieldScript[] leafScripts = null;
|
FieldScript[] leafScripts = null;
|
||||||
List<ScriptFieldsContext.ScriptField> scriptFields = context.scriptFields().fields();
|
List<ScriptFieldsContext.ScriptField> scriptFields = context.scriptFields().fields();
|
||||||
|
|
|
@ -28,8 +28,6 @@ import org.elasticsearch.search.fetch.FetchSubPhase;
|
||||||
import org.elasticsearch.search.internal.SearchContext;
|
import org.elasticsearch.search.internal.SearchContext;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
public final class SeqNoPrimaryTermPhase implements FetchSubPhase {
|
public final class SeqNoPrimaryTermPhase implements FetchSubPhase {
|
||||||
@Override
|
@Override
|
||||||
|
@ -38,9 +36,6 @@ public final class SeqNoPrimaryTermPhase implements FetchSubPhase {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hits = hits.clone(); // don't modify the incoming hits
|
|
||||||
Arrays.sort(hits, Comparator.comparingInt(SearchHit::docId));
|
|
||||||
|
|
||||||
int lastReaderId = -1;
|
int lastReaderId = -1;
|
||||||
NumericDocValues seqNoField = null;
|
NumericDocValues seqNoField = null;
|
||||||
NumericDocValues primaryTermField = null;
|
NumericDocValues primaryTermField = null;
|
||||||
|
|
Loading…
Reference in New Issue