This is an automated email from the ASF dual-hosted git repository.

yashmayya pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new a1455b22319 Rebuild H3 index on segment reload if resolution config is 
updated (#16953)
a1455b22319 is described below

commit a1455b22319b928a1a47a18e801d8f4da08bfa38
Author: Yash Mayya <[email protected]>
AuthorDate: Mon Oct 6 17:55:59 2025 -0700

    Rebuild H3 index on segment reload if resolution config is updated (#16953)
---
 .../index/loader/invertedindex/H3IndexHandler.java | 44 ++++++++++++++++++++++
 .../index/loader/SegmentPreProcessorTest.java      | 26 +++++++++++++
 2 files changed, 70 insertions(+)

diff --git 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/loader/invertedindex/H3IndexHandler.java
 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/loader/invertedindex/H3IndexHandler.java
index 67b9a561289..32d39f6f263 100644
--- 
a/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/loader/invertedindex/H3IndexHandler.java
+++ 
b/pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/loader/invertedindex/H3IndexHandler.java
@@ -20,12 +20,14 @@ package 
org.apache.pinot.segment.local.segment.index.loader.invertedindex;
 
 import com.google.common.base.Preconditions;
 import java.io.File;
+import java.io.IOException;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.io.FileUtils;
 import org.apache.pinot.segment.local.segment.index.loader.BaseIndexHandler;
 import org.apache.pinot.segment.local.segment.index.loader.LoaderUtils;
+import 
org.apache.pinot.segment.local.segment.index.readers.geospatial.ImmutableH3IndexReader;
 import org.apache.pinot.segment.local.utils.GeometrySerializer;
 import org.apache.pinot.segment.spi.ColumnMetadata;
 import org.apache.pinot.segment.spi.V1Constants;
@@ -40,6 +42,7 @@ import 
org.apache.pinot.segment.spi.index.creator.H3IndexConfig;
 import org.apache.pinot.segment.spi.index.reader.Dictionary;
 import org.apache.pinot.segment.spi.index.reader.ForwardIndexReader;
 import org.apache.pinot.segment.spi.index.reader.ForwardIndexReaderContext;
+import org.apache.pinot.segment.spi.index.reader.H3IndexReader;
 import org.apache.pinot.segment.spi.store.SegmentDirectory;
 import org.apache.pinot.spi.config.table.TableConfig;
 import org.apache.pinot.spi.data.FieldSpec.DataType;
@@ -70,6 +73,23 @@ public class H3IndexHandler extends BaseIndexHandler {
       if (!columnsToAddIdx.remove(column)) {
         LOGGER.info("Need to remove existing H3 index from segment: {}, 
column: {}", segmentName, column);
         return true;
+      } else {
+        // Index already exists, check for change in resolution config
+        short newResolution = 
_h3Configs.get(column).getResolution().serialize();
+        short oldResolution;
+        try (H3IndexReader indexReader = new ImmutableH3IndexReader(
+            segmentReader.getIndexFor(column, StandardIndexes.h3()))) {
+          oldResolution = indexReader.getH3IndexResolution().serialize();
+        } catch (IOException e) {
+          LOGGER.warn("Failed to read existing H3 index for segment: {}, 
column: {}", segmentName, column, e);
+          continue;
+        }
+        if (newResolution != oldResolution) {
+          LOGGER.info(
+              "H3 index resolution changed for segment: {}, column: {}, old 
resolution: {}, new resolution: {}."
+                  + " Index needs to be rebuilt.", segmentName, column, 
oldResolution, newResolution);
+          return true;
+        }
       }
     }
     // Check if any new index need to be added.
@@ -95,6 +115,30 @@ public class H3IndexHandler extends BaseIndexHandler {
         LOGGER.info("Removing existing H3 index from segment: {}, column: {}", 
segmentName, column);
         segmentWriter.removeIndex(column, StandardIndexes.h3());
         LOGGER.info("Removed existing H3 index from segment: {}, column: {}", 
segmentName, column);
+      } else {
+        // Index already exists, check for change in resolution config
+        short newResolution = 
_h3Configs.get(column).getResolution().serialize();
+        short oldResolution;
+
+        try (H3IndexReader indexReader = new ImmutableH3IndexReader(
+            segmentWriter.getIndexFor(column, StandardIndexes.h3()))) {
+          oldResolution = indexReader.getH3IndexResolution().serialize();
+        } catch (IOException e) {
+          LOGGER.warn("Failed to read existing H3 index for segment: {}, 
column: {}", segmentName, column, e);
+          segmentWriter.removeIndex(column, StandardIndexes.h3());
+          columnsToAddIdx.add(column);
+          continue;
+        }
+
+        if (newResolution != oldResolution) {
+          LOGGER.info(
+              "H3 index resolution changed for segment: {}, column: {}, old 
resolution: {}, new resolution: {}. "
+                  + "Deleting existing H3 index before rebuilding a new one.",
+              segmentName, column, oldResolution, newResolution);
+          segmentWriter.removeIndex(column, StandardIndexes.h3());
+          LOGGER.info("Removed existing H3 index from segment: {}, column: 
{}", segmentName, column);
+          columnsToAddIdx.add(column);
+        }
       }
     }
     for (String column : columnsToAddIdx) {
diff --git 
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/loader/SegmentPreProcessorTest.java
 
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/loader/SegmentPreProcessorTest.java
index f53f3ba3569..20e395ad375 100644
--- 
a/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/loader/SegmentPreProcessorTest.java
+++ 
b/pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/loader/SegmentPreProcessorTest.java
@@ -1506,6 +1506,32 @@ public class SegmentPreProcessorTest implements 
PinotBuffersAfterClassCheckRule
     });
   }
 
+  @Test(dataProvider = "bothV1AndV3")
+  public void testH3IndexResolutionUpdate(SegmentVersion segmentVersion)
+      throws Exception {
+    buildSegment(segmentVersion);
+
+    // Create H3 index with resolution 5.
+    _fieldConfigMap.put("newH3Col",
+        new FieldConfig("newH3Col", FieldConfig.EncodingType.DICTIONARY, 
List.of(FieldConfig.IndexType.H3), null,
+            Map.of("resolutions", "5")));
+    runPreProcessor(_newColumnsSchemaWithH3Json);
+
+    verifyProcessNotNeeded();
+
+    // Update H3 index resolution to 4
+    _fieldConfigMap.put("newH3Col",
+        new FieldConfig("newH3Col", FieldConfig.EncodingType.DICTIONARY, 
List.of(FieldConfig.IndexType.H3), null,
+            Map.of("resolutions", "4")));
+
+    // Verify that preprocessing is needed, update the index, and verify again 
that no more processing is needed
+    verifyProcessNeeded();
+
+    // Remove new indexes
+    resetIndexConfigs();
+    runPreProcessor(_newColumnsSchemaWithH3Json);
+  }
+
   private void verifyProcessNeeded()
       throws Exception {
     try (SegmentDirectory segmentDirectory = new 
SegmentLocalFSDirectory(INDEX_DIR, ReadMode.mmap);


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

Reply via email to