Skip to content

Commit e21e8a7

Browse files
authored
Use doc values skipper for @timestamp in synthetic _id postings elastic#138568 (elastic#138876)
Follow-up of elastic#138568. Relates ES-13604
1 parent 88ea6ed commit e21e8a7

File tree

2 files changed

+53
-24
lines changed

2 files changed

+53
-24
lines changed

docs/changelog/138876.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 138876
2+
summary: "Use doc values skipper for @timestamp in synthetic `_id` postings #138568"
3+
area: TSDB
4+
type: enhancement
5+
issues: []

server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdFieldsProducer.java

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,25 @@ private int findFirstDocWithTsIdOrdinalEqualTo(int tsIdOrd) throws IOException {
373373
return DocIdSetIterator.NO_MORE_DOCS;
374374
}
375375

376+
/**
377+
* Skip as many documents as possible after a given document ID to find the first document ID matching the timestamp.
378+
*
379+
* @param timestamp the timestamp to match
380+
* @param minDocID the min. document ID
381+
* @return a docID to start scanning documents from in order to find the first document ID matching the provided timestamp
382+
* @throws IOException if any I/O exception occurs
383+
*/
384+
private int skipDocIDForTimestamp(long timestamp, int minDocID) throws IOException {
385+
var skipper = docValuesProducer.getSkipper(timestampFieldInfo);
386+
assert skipper != null;
387+
if (skipper.minValue() > timestamp || timestamp > skipper.maxValue()) {
388+
return DocIdSetIterator.NO_MORE_DOCS;
389+
}
390+
skipper.advance(minDocID);
391+
skipper.advance(timestamp, Long.MAX_VALUE);
392+
return Math.max(minDocID, skipper.minDocID(0));
393+
}
394+
376395
private int getTsIdValueCount() throws IOException {
377396
if (tsIdDocValues == null) {
378397
tsIdDocValues = docValuesProducer.getSorted(tsIdFieldInfo);
@@ -483,32 +502,37 @@ public SeekStatus seekCeil(BytesRef id) throws IOException {
483502
return SeekStatus.END;
484503
}
485504

486-
// _tsid found, extract the timestamp
487-
final long timestamp = TsidExtractingIdFieldMapper.extractTimestampFromSyntheticId(id);
488-
489-
// Find the first document matching the _tsid
490-
final int startDocID = docValues.findFirstDocWithTsIdOrdinalEqualTo(tsIdOrd);
505+
// Find the first document ID matching the _tsid
506+
int startDocID = docValues.findFirstDocWithTsIdOrdinalEqualTo(tsIdOrd);
491507
assert startDocID >= 0 : startDocID;
492508

493-
int docID = startDocID;
494-
int docTsIdOrd = tsIdOrd;
495-
long docTimestamp;
496-
497-
// Iterate over documents to find the first one matching the timestamp
498-
for (; docID < maxDocs; docID++) {
499-
docTimestamp = docValues.docTimestamp(docID);
500-
if (startDocID < docID) {
501-
// After the first doc, we need to check again if _tsid matches
502-
docTsIdOrd = docValues.docTsIdOrdinal(docID);
503-
}
504-
if (docTsIdOrd == tsIdOrd && docTimestamp == timestamp) {
505-
// It's a match!
506-
current = new SyntheticTerm(docID, tsIdOrd, tsId, docTimestamp, docValues.docRoutingHash(docID));
507-
return SeekStatus.FOUND;
508-
}
509-
// Remaining docs don't match, stop here
510-
if (tsIdOrd < docTsIdOrd || docTimestamp < timestamp) {
511-
break;
509+
if (startDocID != DocIdSetIterator.NO_MORE_DOCS) {
510+
// _tsid found, extract the timestamp
511+
final long timestamp = TsidExtractingIdFieldMapper.extractTimestampFromSyntheticId(id);
512+
513+
startDocID = docValues.skipDocIDForTimestamp(timestamp, startDocID);
514+
if (startDocID != DocIdSetIterator.NO_MORE_DOCS) {
515+
int docID = startDocID;
516+
int docTsIdOrd = tsIdOrd;
517+
long docTimestamp;
518+
519+
// Iterate over documents to find the first one matching the timestamp
520+
for (; docID < maxDocs; docID++) {
521+
docTimestamp = docValues.docTimestamp(docID);
522+
if (startDocID < docID) {
523+
// After the first doc, we need to check again if _tsid matches
524+
docTsIdOrd = docValues.docTsIdOrdinal(docID);
525+
}
526+
if (docTsIdOrd == tsIdOrd && docTimestamp == timestamp) {
527+
// It's a match!
528+
current = new SyntheticTerm(docID, tsIdOrd, tsId, docTimestamp, docValues.docRoutingHash(docID));
529+
return SeekStatus.FOUND;
530+
}
531+
// Remaining docs don't match, stop here
532+
if (tsIdOrd < docTsIdOrd || docTimestamp < timestamp) {
533+
break;
534+
}
535+
}
512536
}
513537
}
514538
current = NO_MORE_DOCS;

0 commit comments

Comments
 (0)