|
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,11 @@ 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) { |
| 97 | + var primaryField = indexSort.getSort()[0]; |
| 98 | + primarySortFieldNumber = state.fieldInfos.fieldInfo(primaryField.getField()).number; |
| 99 | + } |
95 | 100 | } catch (Throwable exception) { |
96 | 101 | priorE = exception; |
97 | 102 | } finally { |
@@ -333,10 +338,10 @@ public boolean advanceExact(int target) throws IOException { |
333 | 338 | @Override |
334 | 339 | public SortedDocValues getSorted(FieldInfo field) throws IOException { |
335 | 340 | SortedEntry entry = sorted.get(field.number); |
336 | | - return getSorted(entry); |
| 341 | + return getSorted(entry, field.number == primarySortFieldNumber); |
337 | 342 | } |
338 | 343 |
|
339 | | - private SortedDocValues getSorted(SortedEntry entry) throws IOException { |
| 344 | + private SortedDocValues getSorted(SortedEntry entry, boolean valuesSorted) throws IOException { |
340 | 345 | final NumericDocValues ords = getNumeric(entry.ordsEntry, entry.termsDictEntry.termsDictSize); |
341 | 346 | return new BaseSortedDocValues(entry) { |
342 | 347 |
|
@@ -369,10 +374,27 @@ public int advance(int target) throws IOException { |
369 | 374 | public long cost() { |
370 | 375 | return ords.cost(); |
371 | 376 | } |
| 377 | + |
| 378 | + @Override |
| 379 | + public BlockLoader.Block tryReadColumnAtATime(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException { |
| 380 | + final int docCount = docs.count(); |
| 381 | + if (valuesSorted && ords instanceof BaseDenseNumericValues denseOrds) { |
| 382 | + int firstDoc = docs.get(offset); |
| 383 | + denseOrds.advanceExact(firstDoc); |
| 384 | + long startValue = denseOrds.longValue(); |
| 385 | + int lastDoc = docs.get(docCount - 1); |
| 386 | + long lastValue = denseOrds.lookAheadValueAt(lastDoc); |
| 387 | + if (lastValue == startValue) { |
| 388 | + BytesRef b = lookupOrd(Math.toIntExact(startValue)); |
| 389 | + return factory.constantBytes(BytesRef.deepCopyOf(b), docCount); |
| 390 | + } |
| 391 | + } |
| 392 | + return null; |
| 393 | + } |
372 | 394 | }; |
373 | 395 | } |
374 | 396 |
|
375 | | - abstract class BaseSortedDocValues extends SortedDocValues { |
| 397 | + abstract class BaseSortedDocValues extends SortedDocValues implements BlockLoader.OptionalColumnAtATimeReader { |
376 | 398 |
|
377 | 399 | final SortedEntry entry; |
378 | 400 | final TermsEnum termsEnum; |
@@ -406,6 +428,15 @@ public int lookupTerm(BytesRef key) throws IOException { |
406 | 428 | public TermsEnum termsEnum() throws IOException { |
407 | 429 | return new TermsDict(entry.termsDictEntry, data, merging); |
408 | 430 | } |
| 431 | + |
| 432 | + @Override |
| 433 | + public BlockLoader.Block tryReadColumnAtATime(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException { |
| 434 | + return null; |
| 435 | + } |
| 436 | + } |
| 437 | + |
| 438 | + abstract static class BaseDenseNumericValues extends NumericDocValues implements BlockLoader.OptionalColumnAtATimeReader { |
| 439 | + abstract long lookAheadValueAt(int targetDoc) throws IOException; |
409 | 440 | } |
410 | 441 |
|
411 | 442 | abstract static class BaseSortedSetDocValues extends SortedSetDocValues { |
@@ -695,7 +726,7 @@ public SortedNumericDocValues getSortedNumeric(FieldInfo field) throws IOExcepti |
695 | 726 | public SortedSetDocValues getSortedSet(FieldInfo field) throws IOException { |
696 | 727 | SortedSetEntry entry = sortedSets.get(field.number); |
697 | 728 | if (entry.singleValueEntry != null) { |
698 | | - return DocValues.singleton(getSorted(entry.singleValueEntry)); |
| 729 | + return DocValues.singleton(getSorted(entry.singleValueEntry, field.number == primarySortFieldNumber)); |
699 | 730 | } |
700 | 731 |
|
701 | 732 | SortedNumericEntry ordsEntry = entry.ordsEntry; |
@@ -1141,13 +1172,18 @@ public long longValue() { |
1141 | 1172 | final int bitsPerOrd = maxOrd >= 0 ? PackedInts.bitsRequired(maxOrd - 1) : -1; |
1142 | 1173 | if (entry.docsWithFieldOffset == -1) { |
1143 | 1174 | // dense |
1144 | | - return new BulkNumericDocValues() { |
| 1175 | + return new BaseDenseNumericValues() { |
1145 | 1176 |
|
1146 | 1177 | private final int maxDoc = ES819TSDBDocValuesProducer.this.maxDoc; |
1147 | 1178 | private int doc = -1; |
1148 | 1179 | private final TSDBDocValuesEncoder decoder = new TSDBDocValuesEncoder(ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE); |
1149 | 1180 | private long currentBlockIndex = -1; |
1150 | 1181 | private final long[] currentBlock = new long[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; |
| 1182 | + // lookahead block |
| 1183 | + private long lookaheadBlockIndex = -1; |
| 1184 | + private long[] lookaheadBlock; |
| 1185 | + private IndexInput lookaheadData = null; |
| 1186 | + |
1151 | 1187 |
|
1152 | 1188 | @Override |
1153 | 1189 | public int docID() { |
@@ -1183,24 +1219,28 @@ public long longValue() throws IOException { |
1183 | 1219 | final int index = doc; |
1184 | 1220 | final int blockIndex = index >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; |
1185 | 1221 | 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 | | - } |
| 1222 | + if(blockIndex == currentBlockIndex) { |
| 1223 | + return currentBlock[blockInIndex]; |
| 1224 | + } |
| 1225 | + if (blockIndex == lookaheadBlockIndex) { |
| 1226 | + return lookaheadBlock[blockInIndex]; |
| 1227 | + } |
| 1228 | + assert blockIndex > currentBlockIndex : blockIndex + " < " + currentBlockIndex; |
| 1229 | + // no need to seek if the loading block is the next block |
| 1230 | + if (currentBlockIndex + 1 != blockIndex) { |
| 1231 | + valuesData.seek(indexReader.get(blockIndex)); |
| 1232 | + } |
| 1233 | + currentBlockIndex = blockIndex; |
| 1234 | + if (maxOrd >= 0) { |
| 1235 | + decoder.decodeOrdinals(valuesData, currentBlock, bitsPerOrd); |
| 1236 | + } else { |
| 1237 | + decoder.decode(valuesData, currentBlock); |
1198 | 1238 | } |
1199 | 1239 | return currentBlock[blockInIndex]; |
1200 | 1240 | } |
1201 | 1241 |
|
1202 | 1242 | @Override |
1203 | | - public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException { |
| 1243 | + public BlockLoader.Block tryReadColumnAtATime(BlockLoader.BlockFactory factory, BlockLoader.Docs docs, int offset) throws IOException { |
1204 | 1244 | assert maxOrd == -1 : "unexpected maxOrd[" + maxOrd + "]"; |
1205 | 1245 | final int docsCount = docs.count(); |
1206 | 1246 | doc = docs.get(docsCount - 1); |
@@ -1238,6 +1278,32 @@ public BlockLoader.Block read(BlockLoader.BlockFactory factory, BlockLoader.Docs |
1238 | 1278 | } |
1239 | 1279 | } |
1240 | 1280 |
|
| 1281 | + @Override |
| 1282 | + long lookAheadValueAt(int targetDoc) throws IOException { |
| 1283 | + final int blockIndex = targetDoc >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; |
| 1284 | + final int valueIndex = targetDoc & ES819TSDBDocValuesFormat.NUMERIC_BLOCK_MASK; |
| 1285 | + if(blockIndex == currentBlockIndex) { |
| 1286 | + return currentBlock[valueIndex]; |
| 1287 | + } |
| 1288 | + // load data to the lookahead block |
| 1289 | + if (lookaheadBlockIndex != blockIndex) { |
| 1290 | + if (lookaheadBlock == null) { |
| 1291 | + lookaheadBlock = new long[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; |
| 1292 | + lookaheadData = data.slice("look_ahead_values", entry.valuesOffset, entry.valuesLength); |
| 1293 | + } |
| 1294 | + if (lookaheadBlockIndex + 1 != blockIndex) { |
| 1295 | + lookaheadData.seek(indexReader.get(blockIndex)); |
| 1296 | + } |
| 1297 | + if (maxOrd >= 0) { |
| 1298 | + decoder.decodeOrdinals(lookaheadData, lookaheadBlock, bitsPerOrd); |
| 1299 | + } else { |
| 1300 | + decoder.decode(lookaheadData, lookaheadBlock); |
| 1301 | + } |
| 1302 | + lookaheadBlockIndex = blockIndex; |
| 1303 | + } |
| 1304 | + return lookaheadBlock[valueIndex]; |
| 1305 | + } |
| 1306 | + |
1241 | 1307 | static boolean isDense(int firstDocId, int lastDocId, int length) { |
1242 | 1308 | // This does not detect duplicate docids (e.g [1, 1, 2, 4] would be detected as dense), |
1243 | 1309 | // this can happen with enrich or lookup. However this codec isn't used for enrich / lookup. |
|
0 commit comments