|
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