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

justinchen pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/dev/1.3 by this push:
     new bee05d1afb2 [To dev/1.3] Pipe: Optimize TsFile parsing logic (#16173) 
(#16207)
bee05d1afb2 is described below

commit bee05d1afb29e0ad9563b2392b37dfe2a028e6f7
Author: Zhenyu Luo <[email protected]>
AuthorDate: Wed Aug 20 09:44:10 2025 +0800

    [To dev/1.3] Pipe: Optimize TsFile parsing logic (#16173) (#16207)
    
    * Pipe: Optimize TsFile parsing logic
    
    * update
    
    (cherry picked from commit 0dc583e9c59433845d715351b6fa746a92abb5be)
---
 .../container/TsFileInsertionDataContainer.java    |  10 +-
 .../query/TsFileInsertionQueryDataContainer.java   | 145 +++++++++++----------
 .../TsFileInsertionQueryDataTabletIterator.java    |  14 +-
 .../scan/TsFileInsertionScanDataContainer.java     | 103 ++++++++-------
 4 files changed, 150 insertions(+), 122 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/TsFileInsertionDataContainer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/TsFileInsertionDataContainer.java
index 16ca1aff79d..77ef2c871cb 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/TsFileInsertionDataContainer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/TsFileInsertionDataContainer.java
@@ -20,6 +20,7 @@
 package org.apache.iotdb.db.pipe.event.common.tsfile.container;
 
 import org.apache.iotdb.commons.pipe.agent.task.meta.PipeTaskMeta;
+import org.apache.iotdb.commons.pipe.config.PipeConfig;
 import org.apache.iotdb.commons.pipe.datastructure.pattern.PipePattern;
 import org.apache.iotdb.commons.pipe.event.EnrichedEvent;
 import org.apache.iotdb.db.pipe.metric.overview.PipeTsFileToTabletsMetrics;
@@ -55,6 +56,8 @@ public abstract class TsFileInsertionDataContainer implements 
AutoCloseable {
 
   protected TsFileSequenceReader tsFileSequenceReader;
 
+  protected Iterable<TabletInsertionEvent> tabletInsertionIterable;
+
   protected TsFileInsertionDataContainer(
       final String pipeName,
       final long creationTime,
@@ -77,7 +80,9 @@ public abstract class TsFileInsertionDataContainer implements 
AutoCloseable {
 
     // Allocate empty memory block, will be resized later.
     this.allocatedMemoryBlockForTablet =
-        
PipeDataNodeResourceManager.memory().forceAllocateForTabletWithRetry(0);
+        PipeDataNodeResourceManager.memory()
+            .forceAllocateForTabletWithRetry(
+                
PipeConfig.getInstance().getPipeDataStructureTabletSizeInBytes());
   }
 
   /**
@@ -87,6 +92,9 @@ public abstract class TsFileInsertionDataContainer implements 
AutoCloseable {
 
   @Override
   public void close() {
+
+    tabletInsertionIterable = null;
+
     try {
       if (pipeName != null && !timeUsageReported) {
         PipeTsFileToTabletsMetrics.getInstance()
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/query/TsFileInsertionQueryDataContainer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/query/TsFileInsertionQueryDataContainer.java
index d020228863a..897d820df90 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/query/TsFileInsertionQueryDataContainer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/query/TsFileInsertionQueryDataContainer.java
@@ -276,76 +276,83 @@ public class TsFileInsertionQueryDataContainer extends 
TsFileInsertionDataContai
 
   @Override
   public Iterable<TabletInsertionEvent> toTabletInsertionEvents() {
-    return () ->
-        new Iterator<TabletInsertionEvent>() {
-
-          private TsFileInsertionQueryDataTabletIterator tabletIterator = null;
-
-          @Override
-          public boolean hasNext() {
-            while (tabletIterator == null || !tabletIterator.hasNext()) {
-              if (!deviceMeasurementsMapIterator.hasNext()) {
-                close();
-                return false;
-              }
-
-              final Map.Entry<IDeviceID, List<String>> entry = 
deviceMeasurementsMapIterator.next();
-
-              try {
-                tabletIterator =
-                    new TsFileInsertionQueryDataTabletIterator(
-                        tsFileReader,
-                        measurementDataTypeMap,
-                        ((PlainDeviceID) entry.getKey()).toStringID(),
-                        entry.getValue(),
-                        timeFilterExpression,
-                        allocatedMemoryBlockForTablet);
-              } catch (final Exception e) {
-                close();
-                throw new PipeException("failed to create 
TsFileInsertionDataTabletIterator", e);
-              }
-            }
-
-            return true;
-          }
+    if (tabletInsertionIterable == null) {
+      tabletInsertionIterable =
+          () ->
+              new Iterator<TabletInsertionEvent>() {
+
+                private TsFileInsertionQueryDataTabletIterator tabletIterator 
= null;
+
+                @Override
+                public boolean hasNext() {
+                  while (tabletIterator == null || !tabletIterator.hasNext()) {
+                    if (!deviceMeasurementsMapIterator.hasNext()) {
+                      close();
+                      return false;
+                    }
+
+                    final Map.Entry<IDeviceID, List<String>> entry =
+                        deviceMeasurementsMapIterator.next();
+
+                    try {
+                      tabletIterator =
+                          new TsFileInsertionQueryDataTabletIterator(
+                              tsFileReader,
+                              measurementDataTypeMap,
+                              ((PlainDeviceID) entry.getKey()).toStringID(),
+                              entry.getValue(),
+                              timeFilterExpression,
+                              allocatedMemoryBlockForTablet);
+                    } catch (final Exception e) {
+                      close();
+                      throw new PipeException(
+                          "failed to create 
TsFileInsertionDataTabletIterator", e);
+                    }
+                  }
+
+                  return true;
+                }
+
+                @Override
+                public TabletInsertionEvent next() {
+                  if (!hasNext()) {
+                    close();
+                    throw new NoSuchElementException();
+                  }
+
+                  final Tablet tablet = tabletIterator.next();
+                  final boolean isAligned =
+                      deviceIsAlignedMap.getOrDefault(new 
PlainDeviceID(tablet.deviceId), false);
+
+                  final TabletInsertionEvent next;
+                  if (!hasNext()) {
+                    next =
+                        new PipeRawTabletInsertionEvent(
+                            tablet,
+                            isAligned,
+                            sourceEvent != null ? sourceEvent.getPipeName() : 
null,
+                            sourceEvent != null ? 
sourceEvent.getCreationTime() : 0,
+                            pipeTaskMeta,
+                            sourceEvent,
+                            true);
+                    close();
+                  } else {
+                    next =
+                        new PipeRawTabletInsertionEvent(
+                            tablet,
+                            isAligned,
+                            sourceEvent != null ? sourceEvent.getPipeName() : 
null,
+                            sourceEvent != null ? 
sourceEvent.getCreationTime() : 0,
+                            pipeTaskMeta,
+                            sourceEvent,
+                            false);
+                  }
+                  return next;
+                }
+              };
+    }
 
-          @Override
-          public TabletInsertionEvent next() {
-            if (!hasNext()) {
-              close();
-              throw new NoSuchElementException();
-            }
-
-            final Tablet tablet = tabletIterator.next();
-            final boolean isAligned =
-                deviceIsAlignedMap.getOrDefault(new 
PlainDeviceID(tablet.deviceId), false);
-
-            final TabletInsertionEvent next;
-            if (!hasNext()) {
-              next =
-                  new PipeRawTabletInsertionEvent(
-                      tablet,
-                      isAligned,
-                      sourceEvent != null ? sourceEvent.getPipeName() : null,
-                      sourceEvent != null ? sourceEvent.getCreationTime() : 0,
-                      pipeTaskMeta,
-                      sourceEvent,
-                      true);
-              close();
-            } else {
-              next =
-                  new PipeRawTabletInsertionEvent(
-                      tablet,
-                      isAligned,
-                      sourceEvent != null ? sourceEvent.getPipeName() : null,
-                      sourceEvent != null ? sourceEvent.getCreationTime() : 0,
-                      pipeTaskMeta,
-                      sourceEvent,
-                      false);
-            }
-            return next;
-          }
-        };
+    return tabletInsertionIterable;
   }
 
   @Override
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/query/TsFileInsertionQueryDataTabletIterator.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/query/TsFileInsertionQueryDataTabletIterator.java
index f9fa5a9d283..5fa252412d4 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/query/TsFileInsertionQueryDataTabletIterator.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/query/TsFileInsertionQueryDataTabletIterator.java
@@ -60,6 +60,8 @@ public class TsFileInsertionQueryDataTabletIterator 
implements Iterator<Tablet>
 
   private final PipeMemoryBlock allocatedBlockForTablet;
 
+  private RowRecord rowRecord;
+
   TsFileInsertionQueryDataTabletIterator(
       final TsFileReader tsFileReader,
       final Map<String, TSDataType> measurementDataTypeMap,
@@ -130,22 +132,24 @@ public class TsFileInsertionQueryDataTabletIterator 
implements Iterator<Tablet>
     if (!queryDataSet.hasNext()) {
       tablet = new Tablet(deviceId, schemas, 1);
       tablet.initBitMaps();
-      // Ignore the memory cost of tablet
-      
PipeDataNodeResourceManager.memory().forceResize(allocatedBlockForTablet, 0);
       return tablet;
     }
 
     boolean isFirstRow = true;
     while (queryDataSet.hasNext()) {
-      final RowRecord rowRecord = queryDataSet.next();
+      final RowRecord rowRecord = this.rowRecord != null ? this.rowRecord : 
queryDataSet.next();
       if (isFirstRow) {
         // Calculate row count and memory size of the tablet based on the 
first row
+        this.rowRecord = rowRecord; // Save the first row for later use
         Pair<Integer, Integer> rowCountAndMemorySize =
             PipeMemoryWeightUtil.calculateTabletRowCountAndMemory(rowRecord);
         tablet = new Tablet(deviceId, schemas, 
rowCountAndMemorySize.getLeft());
         tablet.initBitMaps();
-        PipeDataNodeResourceManager.memory()
-            .forceResize(allocatedBlockForTablet, 
rowCountAndMemorySize.getRight());
+        if (allocatedBlockForTablet.getMemoryUsageInBytes() < 
rowCountAndMemorySize.getRight()) {
+          PipeDataNodeResourceManager.memory()
+              .forceResize(allocatedBlockForTablet, 
rowCountAndMemorySize.getRight());
+        }
+        this.rowRecord = null; // Clear the saved first row
         isFirstRow = false;
       }
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/scan/TsFileInsertionScanDataContainer.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/scan/TsFileInsertionScanDataContainer.java
index f93642cb9d1..30006b35808 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/scan/TsFileInsertionScanDataContainer.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/event/common/tsfile/container/scan/TsFileInsertionScanDataContainer.java
@@ -111,7 +111,9 @@ public class TsFileInsertionScanDataContainer extends 
TsFileInsertionDataContain
 
     // Allocate empty memory block, will be resized later.
     this.allocatedMemoryBlockForBatchData =
-        
PipeDataNodeResourceManager.memory().forceAllocateForTabletWithRetry(0);
+        PipeDataNodeResourceManager.memory()
+            .forceAllocateForTabletWithRetry(
+                
PipeConfig.getInstance().getPipeDataStructureTabletSizeInBytes());
 
     try {
       tsFileSequenceReader = new 
TsFileSequenceReader(tsFile.getAbsolutePath(), false, false);
@@ -137,44 +139,50 @@ public class TsFileInsertionScanDataContainer extends 
TsFileInsertionDataContain
 
   @Override
   public Iterable<TabletInsertionEvent> toTabletInsertionEvents() {
-    return () ->
-        new Iterator<TabletInsertionEvent>() {
-
-          @Override
-          public boolean hasNext() {
-            return Objects.nonNull(chunkReader);
-          }
-
-          @Override
-          public TabletInsertionEvent next() {
-            if (!hasNext()) {
-              close();
-              throw new NoSuchElementException();
-            }
-
-            // currentIsAligned is initialized when 
TsFileInsertionEventScanParser is constructed.
-            // When the getNextTablet function is called, currentIsAligned may 
be updated, causing
-            // the currentIsAligned information to be inconsistent with the 
current Tablet
-            // information.
-            final boolean isAligned = currentIsAligned;
-            final Tablet tablet = getNextTablet();
-            final boolean hasNext = hasNext();
-            try {
-              return new PipeRawTabletInsertionEvent(
-                  tablet,
-                  isAligned,
-                  sourceEvent != null ? sourceEvent.getPipeName() : null,
-                  sourceEvent != null ? sourceEvent.getCreationTime() : 0,
-                  pipeTaskMeta,
-                  sourceEvent,
-                  !hasNext);
-            } finally {
-              if (!hasNext) {
-                close();
-              }
-            }
-          }
-        };
+    if (tabletInsertionIterable == null) {
+      tabletInsertionIterable =
+          () ->
+              new Iterator<TabletInsertionEvent>() {
+
+                @Override
+                public boolean hasNext() {
+                  return Objects.nonNull(chunkReader);
+                }
+
+                @Override
+                public TabletInsertionEvent next() {
+                  if (!hasNext()) {
+                    close();
+                    throw new NoSuchElementException();
+                  }
+
+                  // currentIsAligned is initialized when 
TsFileInsertionEventScanParser is
+                  // constructed.
+                  // When the getNextTablet function is called, 
currentIsAligned may be updated,
+                  // causing
+                  // the currentIsAligned information to be inconsistent with 
the current Tablet
+                  // information.
+                  final boolean isAligned = currentIsAligned;
+                  final Tablet tablet = getNextTablet();
+                  final boolean hasNext = hasNext();
+                  try {
+                    return new PipeRawTabletInsertionEvent(
+                        tablet,
+                        isAligned,
+                        sourceEvent != null ? sourceEvent.getPipeName() : null,
+                        sourceEvent != null ? sourceEvent.getCreationTime() : 
0,
+                        pipeTaskMeta,
+                        sourceEvent,
+                        !hasNext);
+                  } finally {
+                    if (!hasNext) {
+                      close();
+                    }
+                  }
+                }
+              };
+    }
+    return tabletInsertionIterable;
   }
 
   public Iterable<Pair<Tablet, Boolean>> toTabletWithIsAligneds() {
@@ -233,8 +241,11 @@ public class TsFileInsertionScanDataContainer extends 
TsFileInsertionDataContain
             tablet =
                 new Tablet(currentDevice, currentMeasurements, 
rowCountAndMemorySize.getLeft());
             tablet.initBitMaps();
-            PipeDataNodeResourceManager.memory()
-                .forceResize(allocatedMemoryBlockForTablet, 
rowCountAndMemorySize.getRight());
+            if (allocatedMemoryBlockForTablet.getMemoryUsageInBytes()
+                < rowCountAndMemorySize.getRight()) {
+              PipeDataNodeResourceManager.memory()
+                  .forceResize(allocatedMemoryBlockForTablet, 
rowCountAndMemorySize.getRight());
+            }
             isFirstRow = false;
           }
 
@@ -259,8 +270,6 @@ public class TsFileInsertionScanDataContainer extends 
TsFileInsertionDataContain
       if (tablet == null) {
         tablet = new Tablet(currentDevice, currentMeasurements, 1);
         tablet.initBitMaps();
-        // Ignore the memory cost of tablet
-        
PipeDataNodeResourceManager.memory().forceResize(allocatedMemoryBlockForTablet, 
0);
       }
 
       // Switch chunk reader iff current chunk is all consumed
@@ -287,10 +296,10 @@ public class TsFileInsertionScanDataContainer extends 
TsFileInsertionDataContain
 
       do {
         data = chunkReader.nextPageData();
-        PipeDataNodeResourceManager.memory()
-            .forceResize(
-                allocatedMemoryBlockForBatchData,
-                PipeMemoryWeightUtil.calculateBatchDataRamBytesUsed(data));
+        long size = PipeMemoryWeightUtil.calculateBatchDataRamBytesUsed(data);
+        if (allocatedMemoryBlockForBatchData.getMemoryUsageInBytes() < size) {
+          
PipeDataNodeResourceManager.memory().forceResize(allocatedMemoryBlockForBatchData,
 size);
+        }
       } while (!data.hasCurrent() && chunkReader.hasNextSatisfiedPage());
     } while (!data.hasCurrent());
   }

Reply via email to