xiangfu0 commented on code in PR #18891:
URL: https://github.com/apache/pinot/pull/18891#discussion_r3532886919


##########
pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/json/ImmutableJsonIndexReader.java:
##########
@@ -783,34 +797,76 @@ public String[][] getValuesMV(int[] docIds, int length, 
Map<String, RoaringBitma
   @Override
   public String[] getValuesSV(int[] docIds, int length, Map<String, 
RoaringBitmap> valueToMatchingDocs,
       boolean isFlattenedDocIds) {
-    Int2ObjectOpenHashMap<String> docIdToValues = new 
Int2ObjectOpenHashMap<>(docIds.length);
-    RoaringBitmap docIdMask = RoaringBitmap.bitmapOf(docIds);
-
-    for (Map.Entry<String, RoaringBitmap> entry : 
valueToMatchingDocs.entrySet()) {
-      String value = entry.getKey();
-      RoaringBitmap matchingDocIds = entry.getValue();
-      if (isFlattenedDocIds) {
-        matchingDocIds.forEach((IntConsumer) flattenedDocId -> {
+    String[] values = new String[length];
+    if (length == 0) {
+      return values;
+    }
+
+    if (isFlattenedDocIds) {
+      // Flattened doc ids must be converted to real doc ids before they can 
be matched against the block's doc ids,
+      // so we still build a docId -> value lookup keyed by the converted doc 
id.
+      Int2ObjectOpenHashMap<String> docIdToValues = new 
Int2ObjectOpenHashMap<>(length);
+      RoaringBitmap docIdMask = RoaringBitmap.bitmapOf(docIds);
+      for (Map.Entry<String, RoaringBitmap> entry : 
valueToMatchingDocs.entrySet()) {
+        String value = entry.getKey();
+        entry.getValue().forEach((IntConsumer) flattenedDocId -> {
           int docId = getDocId(flattenedDocId);
           if (docIdMask.contains(docId)) {
             docIdToValues.put(docId, value);
           }
         });
-      } else {
-        RoaringBitmap intersection = RoaringBitmap.and(matchingDocIds, 
docIdMask);
-        if (intersection.isEmpty()) {
-          continue;
+      }
+      for (int i = 0; i < length; i++) {
+        values[i] = docIdToValues.get(docIds[i]);
+      }
+      return values;
+    }
+
+    // Non-flattened path (the only path used by jsonExtractIndex SV): docIds 
are real, ascending-sorted doc ids for
+    // the current block, and for a single-value path each doc belongs to at 
most one value's posting list. We can
+    // therefore scatter values directly, iterating each value's posting list 
only over the block's [lo, hi] doc id
+    // range with a peekable iterator. This avoids allocating a per-block doc 
id mask bitmap, a RoaringBitmap.and per
+    // distinct value, and an intermediate docId -> value hash map.
+    int lo = docIds[0];

Review Comment:
   This assumes the block docIds are ascending, but selection queries can run 
the TransformOperator over DESC doc-id blocks when ordering by a sorted column 
via withOrder(DESC). In that case lo > hi, so the range scan never fills 
matching values and jsonExtractIndex can return null/default or throw for rows 
that do have the path. Keep the order-insensitive mask path unless ascending is 
guaranteed, or detect non-ascending blocks and scatter with the true min/max 
range.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to