|
53 | 53 |
|
54 | 54 | final class ES819TSDBDocValuesProducer extends DocValuesProducer { |
55 | 55 | final IntObjectHashMap<NumericEntry> numerics; |
| 56 | + private int primarySortFieldNumber = -1; |
56 | 57 | final IntObjectHashMap<BinaryEntry> binaries; |
57 | 58 | final IntObjectHashMap<SortedEntry> sorted; |
58 | 59 | final IntObjectHashMap<SortedSetEntry> sortedSets; |
@@ -91,7 +92,14 @@ final class ES819TSDBDocValuesProducer extends DocValuesProducer { |
91 | 92 | ); |
92 | 93 |
|
93 | 94 | readFields(in, state.fieldInfos); |
94 | | - |
| 95 | + final var indexSort = state.segmentInfo.getIndexSort(); |
| 96 | + if (indexSort != null && indexSort.getSort().length > 0) { |
| 97 | + var primarySortField = indexSort.getSort()[0]; |
| 98 | + var sortField = state.fieldInfos.fieldInfo(primarySortField.getField()); |
| 99 | + if (sortField != null) { |
| 100 | + primarySortFieldNumber = sortField.number; |
| 101 | + } |
| 102 | + } |
95 | 103 | } catch (Throwable exception) { |
96 | 104 | priorE = exception; |
97 | 105 | } finally { |
@@ -333,10 +341,10 @@ public boolean advanceExact(int target) throws IOException { |
333 | 341 | @Override |
334 | 342 | public SortedDocValues getSorted(FieldInfo field) throws IOException { |
335 | 343 | SortedEntry entry = sorted.get(field.number); |
336 | | - return getSorted(entry); |
| 344 | + return getSorted(entry, field.number == primarySortFieldNumber); |
337 | 345 | } |
338 | 346 |
|
339 | | - private SortedDocValues getSorted(SortedEntry entry) throws IOException { |
| 347 | + private SortedDocValues getSorted(SortedEntry entry, boolean valuesSorted) throws IOException { |
340 | 348 | final NumericDocValues ords = getNumeric(entry.ordsEntry, entry.termsDictEntry.termsDictSize); |
341 | 349 | return new BaseSortedDocValues(entry) { |
342 | 350 |
|
@@ -369,10 +377,29 @@ public int advance(int target) throws IOException { |
369 | 377 | public long cost() { |
370 | 378 | return ords.cost(); |
371 | 379 | } |
| 380 | + |
| 381 | + @Override |
| 382 | + public BlockLoader.Block tryRead(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException { |
| 383 | + if (valuesSorted && ords instanceof BaseDenseNumericValues denseOrds) { |
| 384 | + int firstDoc = docs.get(offset); |
| 385 | + denseOrds.advanceExact(firstDoc); |
| 386 | + long startValue = denseOrds.longValue(); |
| 387 | + final int docCount = docs.count(); |
| 388 | + int lastDoc = docs.get(docCount - 1); |
| 389 | + long lastValue = denseOrds.lookAheadValueAt(lastDoc); |
| 390 | + if (lastValue == startValue) { |
| 391 | + BytesRef b = lookupOrd(Math.toIntExact(startValue)); |
| 392 | + return factory.constantBytes(BytesRef.deepCopyOf(b), docCount - offset); |
| 393 | + } |
| 394 | + // TODO: Since ordinals are sorted, start at 0 (offset by startValue), scan until lastValue, |
| 395 | + // then fill remaining positions with lastValue. |
| 396 | + } |
| 397 | + return null; |
| 398 | + } |
372 | 399 | }; |
373 | 400 | } |
374 | 401 |
|
375 | | - abstract class BaseSortedDocValues extends SortedDocValues { |
| 402 | + abstract class BaseSortedDocValues extends SortedDocValues implements BlockLoader.OptionalColumnAtATimeReader { |
376 | 403 |
|
377 | 404 | final SortedEntry entry; |
378 | 405 | final TermsEnum termsEnum; |
@@ -406,6 +433,15 @@ public int lookupTerm(BytesRef key) throws IOException { |
406 | 433 | public TermsEnum termsEnum() throws IOException { |
407 | 434 | return new TermsDict(entry.termsDictEntry, data, merging); |
408 | 435 | } |
| 436 | + |
| 437 | + @Override |
| 438 | + public BlockLoader.Block tryRead(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException { |
| 439 | + return null; |
| 440 | + } |
| 441 | + } |
| 442 | + |
| 443 | + abstract static class BaseDenseNumericValues extends NumericDocValues implements BlockLoader.OptionalColumnAtATimeReader { |
| 444 | + abstract long lookAheadValueAt(int targetDoc) throws IOException; |
409 | 445 | } |
410 | 446 |
|
411 | 447 | abstract static class BaseSortedSetDocValues extends SortedSetDocValues { |
@@ -695,7 +731,7 @@ public SortedNumericDocValues getSortedNumeric(FieldInfo field) throws IOExcepti |
695 | 731 | public SortedSetDocValues getSortedSet(FieldInfo field) throws IOException { |
696 | 732 | SortedSetEntry entry = sortedSets.get(field.number); |
697 | 733 | if (entry.singleValueEntry != null) { |
698 | | - return DocValues.singleton(getSorted(entry.singleValueEntry)); |
| 734 | + return DocValues.singleton(getSorted(entry.singleValueEntry, field.number == primarySortFieldNumber)); |
699 | 735 | } |
700 | 736 |
|
701 | 737 | SortedNumericEntry ordsEntry = entry.ordsEntry; |
@@ -1047,7 +1083,7 @@ private NumericDocValues getNumeric(NumericEntry entry, long maxOrd) throws IOEx |
1047 | 1083 | // Special case for maxOrd 1, no need to read blocks and use ordinal 0 as only value |
1048 | 1084 | if (entry.docsWithFieldOffset == -1) { |
1049 | 1085 | // Special case when all docs have a value |
1050 | | - return new NumericDocValues() { |
| 1086 | + return new BaseDenseNumericValues() { |
1051 | 1087 |
|
1052 | 1088 | private final int maxDoc = ES819TSDBDocValuesProducer.this.maxDoc; |
1053 | 1089 | private int doc = -1; |
@@ -1086,6 +1122,17 @@ public boolean advanceExact(int target) { |
1086 | 1122 | public long cost() { |
1087 | 1123 | return maxDoc; |
1088 | 1124 | } |
| 1125 | + |
| 1126 | + @Override |
| 1127 | + long lookAheadValueAt(int targetDoc) throws IOException { |
| 1128 | + return 0L; // Only one ordinal! |
| 1129 | + } |
| 1130 | + |
| 1131 | + @Override |
| 1132 | + public BlockLoader.Block tryRead(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) |
| 1133 | + throws IOException { |
| 1134 | + return null; |
| 1135 | + } |
1089 | 1136 | }; |
1090 | 1137 | } else { |
1091 | 1138 | final IndexedDISI disi = new IndexedDISI( |
@@ -1141,13 +1188,17 @@ public long longValue() { |
1141 | 1188 | final int bitsPerOrd = maxOrd >= 0 ? PackedInts.bitsRequired(maxOrd - 1) : -1; |
1142 | 1189 | if (entry.docsWithFieldOffset == -1) { |
1143 | 1190 | // dense |
1144 | | - return new BulkNumericDocValues() { |
| 1191 | + return new BaseDenseNumericValues() { |
1145 | 1192 |
|
1146 | 1193 | private final int maxDoc = ES819TSDBDocValuesProducer.this.maxDoc; |
1147 | 1194 | private int doc = -1; |
1148 | 1195 | private final TSDBDocValuesEncoder decoder = new TSDBDocValuesEncoder(ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE); |
1149 | 1196 | private long currentBlockIndex = -1; |
1150 | 1197 | private final long[] currentBlock = new long[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; |
| 1198 | + // lookahead block |
| 1199 | + private long lookaheadBlockIndex = -1; |
| 1200 | + private long[] lookaheadBlock; |
| 1201 | + private IndexInput lookaheadData = null; |
1151 | 1202 |
|
1152 | 1203 | @Override |
1153 | 1204 | public int docID() { |
@@ -1183,24 +1234,28 @@ public long longValue() throws IOException { |
1183 | 1234 | final int index = doc; |
1184 | 1235 | final int blockIndex = index >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; |
1185 | 1236 | final int blockInIndex = index & ES819TSDBDocValuesFormat.NUMERIC_BLOCK_MASK; |
1186 | | - if (blockIndex != currentBlockIndex) { |
1187 | | - assert blockIndex > currentBlockIndex : blockIndex + " < " + currentBlockIndex; |
1188 | | - // no need to seek if the loading block is the next block |
1189 | | - if (currentBlockIndex + 1 != blockIndex) { |
1190 | | - valuesData.seek(indexReader.get(blockIndex)); |
1191 | | - } |
1192 | | - currentBlockIndex = blockIndex; |
1193 | | - if (maxOrd >= 0) { |
1194 | | - decoder.decodeOrdinals(valuesData, currentBlock, bitsPerOrd); |
1195 | | - } else { |
1196 | | - decoder.decode(valuesData, currentBlock); |
1197 | | - } |
| 1237 | + if (blockIndex == currentBlockIndex) { |
| 1238 | + return currentBlock[blockInIndex]; |
| 1239 | + } |
| 1240 | + if (blockIndex == lookaheadBlockIndex) { |
| 1241 | + return lookaheadBlock[blockInIndex]; |
| 1242 | + } |
| 1243 | + assert blockIndex > currentBlockIndex : blockIndex + " < " + currentBlockIndex; |
| 1244 | + // no need to seek if the loading block is the next block |
| 1245 | + if (currentBlockIndex + 1 != blockIndex) { |
| 1246 | + valuesData.seek(indexReader.get(blockIndex)); |
| 1247 | + } |
| 1248 | + currentBlockIndex = blockIndex; |
| 1249 | + if (maxOrd >= 0) { |
| 1250 | + decoder.decodeOrdinals(valuesData, currentBlock, bitsPerOrd); |
| 1251 | + } else { |
| 1252 | + decoder.decode(valuesData, currentBlock); |
1198 | 1253 | } |
1199 | 1254 | return currentBlock[blockInIndex]; |
1200 | 1255 | } |
1201 | 1256 |
|
1202 | 1257 | @Override |
1203 | | - public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException { |
| 1258 | + public BlockLoader.Block tryRead(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException { |
1204 | 1259 | assert maxOrd == -1 : "unexpected maxOrd[" + maxOrd + "]"; |
1205 | 1260 | final int docsCount = docs.count(); |
1206 | 1261 | doc = docs.get(docsCount - 1); |
@@ -1238,6 +1293,32 @@ public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs |
1238 | 1293 | } |
1239 | 1294 | } |
1240 | 1295 |
|
| 1296 | + @Override |
| 1297 | + long lookAheadValueAt(int targetDoc) throws IOException { |
| 1298 | + final int blockIndex = targetDoc >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; |
| 1299 | + final int valueIndex = targetDoc & ES819TSDBDocValuesFormat.NUMERIC_BLOCK_MASK; |
| 1300 | + if (blockIndex == currentBlockIndex) { |
| 1301 | + return currentBlock[valueIndex]; |
| 1302 | + } |
| 1303 | + // load data to the lookahead block |
| 1304 | + if (lookaheadBlockIndex != blockIndex) { |
| 1305 | + if (lookaheadBlock == null) { |
| 1306 | + lookaheadBlock = new long[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; |
| 1307 | + lookaheadData = data.slice("look_ahead_values", entry.valuesOffset, entry.valuesLength); |
| 1308 | + } |
| 1309 | + if (lookaheadBlockIndex + 1 != blockIndex) { |
| 1310 | + lookaheadData.seek(indexReader.get(blockIndex)); |
| 1311 | + } |
| 1312 | + if (maxOrd == -1L) { |
| 1313 | + decoder.decode(lookaheadData, lookaheadBlock); |
| 1314 | + } else { |
| 1315 | + decoder.decodeOrdinals(lookaheadData, lookaheadBlock, bitsPerOrd); |
| 1316 | + } |
| 1317 | + lookaheadBlockIndex = blockIndex; |
| 1318 | + } |
| 1319 | + return lookaheadBlock[valueIndex]; |
| 1320 | + } |
| 1321 | + |
1241 | 1322 | static boolean isDense(int firstDocId, int lastDocId, int length) { |
1242 | 1323 | // This does not detect duplicate docids (e.g [1, 1, 2, 4] would be detected as dense), |
1243 | 1324 | // this can happen with enrich or lookup. However this codec isn't used for enrich / lookup. |
|
0 commit comments