You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ja...@apache.org on 2022/12/20 09:45:49 UTC

[iotdb] 01/02: fix bug

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

jackietien pushed a commit to branch QueryMetrics
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit e5d744bd856c2cf92a78fb82d69222ffb788fd30
Author: JackieTien97 <ja...@gmail.com>
AuthorDate: Tue Dec 20 12:44:44 2022 +0800

    fix bug
---
 .../db/mpp/execution/operator/AggregationUtil.java |   2 +-
 .../iotdb/tsfile/read/common/block/TsBlock.java    |   2 +-
 .../read/common/block/column/BinaryColumn.java     |  23 +++-
 .../read/common/block/column/BooleanColumn.java    |  22 +++-
 .../read/common/block/column/DoubleColumn.java     |  27 ++++-
 .../read/common/block/column/FloatColumn.java      |  23 +++-
 .../tsfile/read/common/block/column/IntColumn.java |  23 +++-
 .../read/common/block/column/LongColumn.java       |  23 +++-
 .../read/common/block/column/NullColumn.java       |  11 +-
 .../block/column/RunLengthEncodedColumn.java       |   3 -
 .../read/common/block/column/TimeColumn.java       |  13 ++-
 .../iotdb/tsfile/read/filter/GroupByFilter.java    |   6 +-
 .../tsfile/read/reader/page/AlignedPageReader.java |  75 +-----------
 .../tsfile/read/reader/page/TimePageReader.java    |  33 ++++++
 .../tsfile/read/reader/page/ValuePageReader.java   | 129 +++++++++++++++++++++
 15 files changed, 298 insertions(+), 117 deletions(-)

diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/AggregationUtil.java b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/AggregationUtil.java
index 46873b8503..a8f47ff208 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/AggregationUtil.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/execution/operator/AggregationUtil.java
@@ -127,7 +127,7 @@ public class AggregationUtil {
                 ? inputTsBlock.getEndTime() > curTimeRange.getMax()
                 : inputTsBlock.getEndTime() < curTimeRange.getMin());
     return new Pair<>(
-        isAllAggregatorsHasFinalResult(aggregators) || isTsBlockOutOfBound, inputTsBlock);
+        isTsBlockOutOfBound || isAllAggregatorsHasFinalResult(aggregators), inputTsBlock);
   }
 
   /** Append a row of aggregation results to the result tsBlock. */
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/TsBlock.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/TsBlock.java
index 70dad931fb..e04c378de7 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/TsBlock.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/TsBlock.java
@@ -178,7 +178,7 @@ public class TsBlock {
     for (int i = 0; i < subValueColumns.length; i++) {
       subValueColumns[i] = valueColumns[i].subColumn(fromIndex);
     }
-    return new TsBlock(subTimeColumn, subValueColumns);
+    return new TsBlock(false, subTimeColumn.getPositionCount(), subTimeColumn, subValueColumns);
   }
 
   public TsBlock skipFirst() {
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/BinaryColumn.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/BinaryColumn.java
index 85d910fd88..edbfd7ea58 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/BinaryColumn.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/BinaryColumn.java
@@ -70,6 +70,20 @@ public class BinaryColumn implements Column {
     retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);
   }
 
+  BinaryColumn(
+      int arrayOffset,
+      int positionCount,
+      boolean[] valueIsNull,
+      Binary[] values,
+      long retainedSizeInBytes) {
+    this.arrayOffset = arrayOffset;
+    this.positionCount = positionCount;
+    this.values = values;
+    this.valueIsNull = valueIsNull;
+    // TODO we need to sum up all the Binary's retainedSize here
+    this.retainedSizeInBytes = retainedSizeInBytes;
+  }
+
   @Override
   public TSDataType getDataType() {
     return TSDataType.TEXT;
@@ -138,11 +152,12 @@ public class BinaryColumn implements Column {
 
   @Override
   public Column subColumn(int fromIndex) {
-    if (fromIndex > positionCount) {
-      throw new IllegalArgumentException("fromIndex is not valid");
-    }
     return new BinaryColumn(
-        arrayOffset + fromIndex, positionCount - fromIndex, valueIsNull, values);
+        arrayOffset + fromIndex,
+        positionCount - fromIndex,
+        valueIsNull,
+        values,
+        retainedSizeInBytes);
   }
 
   @Override
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/BooleanColumn.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/BooleanColumn.java
index 5dc1d427b6..f72f485cb1 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/BooleanColumn.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/BooleanColumn.java
@@ -69,6 +69,19 @@ public class BooleanColumn implements Column {
     retainedSizeInBytes = (INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values));
   }
 
+  BooleanColumn(
+      int arrayOffset,
+      int positionCount,
+      boolean[] valueIsNull,
+      boolean[] values,
+      long retainedSizeInBytes) {
+    this.arrayOffset = arrayOffset;
+    this.positionCount = positionCount;
+    this.values = values;
+    this.valueIsNull = valueIsNull;
+    this.retainedSizeInBytes = retainedSizeInBytes;
+  }
+
   @Override
   public TSDataType getDataType() {
     return TSDataType.BOOLEAN;
@@ -137,11 +150,12 @@ public class BooleanColumn implements Column {
 
   @Override
   public Column subColumn(int fromIndex) {
-    if (fromIndex > positionCount) {
-      throw new IllegalArgumentException("fromIndex is not valid");
-    }
     return new BooleanColumn(
-        arrayOffset + fromIndex, positionCount - fromIndex, valueIsNull, values);
+        arrayOffset + fromIndex,
+        positionCount - fromIndex,
+        valueIsNull,
+        values,
+        retainedSizeInBytes);
   }
 
   @Override
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/DoubleColumn.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/DoubleColumn.java
index 9b13800838..695a26429b 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/DoubleColumn.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/DoubleColumn.java
@@ -69,6 +69,24 @@ public class DoubleColumn implements Column {
     retainedSizeInBytes = (INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values));
   }
 
+  DoubleColumn(
+      int arrayOffset,
+      int positionCount,
+      boolean[] valueIsNull,
+      double[] values,
+      long retainedSizeInBytes) {
+
+    this.arrayOffset = arrayOffset;
+
+    this.positionCount = positionCount;
+
+    this.values = values;
+
+    this.valueIsNull = valueIsNull;
+
+    this.retainedSizeInBytes = retainedSizeInBytes;
+  }
+
   @Override
   public TSDataType getDataType() {
     return TSDataType.DOUBLE;
@@ -137,11 +155,12 @@ public class DoubleColumn implements Column {
 
   @Override
   public Column subColumn(int fromIndex) {
-    if (fromIndex > positionCount) {
-      throw new IllegalArgumentException("fromIndex is not valid");
-    }
     return new DoubleColumn(
-        arrayOffset + fromIndex, positionCount - fromIndex, valueIsNull, values);
+        arrayOffset + fromIndex,
+        positionCount - fromIndex,
+        valueIsNull,
+        values,
+        retainedSizeInBytes);
   }
 
   @Override
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/FloatColumn.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/FloatColumn.java
index 4d8f3e0440..ab994230ca 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/FloatColumn.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/FloatColumn.java
@@ -68,6 +68,19 @@ public class FloatColumn implements Column {
     retainedSizeInBytes = (INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values));
   }
 
+  FloatColumn(
+      int arrayOffset,
+      int positionCount,
+      boolean[] valueIsNull,
+      float[] values,
+      long retainedSizeInBytes) {
+    this.arrayOffset = arrayOffset;
+    this.positionCount = positionCount;
+    this.values = values;
+    this.valueIsNull = valueIsNull;
+    this.retainedSizeInBytes = retainedSizeInBytes;
+  }
+
   @Override
   public TSDataType getDataType() {
     return TSDataType.FLOAT;
@@ -136,10 +149,12 @@ public class FloatColumn implements Column {
 
   @Override
   public Column subColumn(int fromIndex) {
-    if (fromIndex > positionCount) {
-      throw new IllegalArgumentException("fromIndex is not valid");
-    }
-    return new FloatColumn(arrayOffset + fromIndex, positionCount - fromIndex, valueIsNull, values);
+    return new FloatColumn(
+        arrayOffset + fromIndex,
+        positionCount - fromIndex,
+        valueIsNull,
+        values,
+        retainedSizeInBytes);
   }
 
   @Override
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/IntColumn.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/IntColumn.java
index 120e4f44da..89094f305f 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/IntColumn.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/IntColumn.java
@@ -68,6 +68,19 @@ public class IntColumn implements Column {
     retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);
   }
 
+  IntColumn(
+      int arrayOffset,
+      int positionCount,
+      boolean[] valueIsNull,
+      int[] values,
+      long retainedSizeInBytes) {
+    this.arrayOffset = arrayOffset;
+    this.positionCount = positionCount;
+    this.values = values;
+    this.valueIsNull = valueIsNull;
+    this.retainedSizeInBytes = retainedSizeInBytes;
+  }
+
   @Override
   public TSDataType getDataType() {
     return TSDataType.INT32;
@@ -136,10 +149,12 @@ public class IntColumn implements Column {
 
   @Override
   public Column subColumn(int fromIndex) {
-    if (fromIndex > positionCount) {
-      throw new IllegalArgumentException("fromIndex is not valid");
-    }
-    return new IntColumn(arrayOffset + fromIndex, positionCount - fromIndex, valueIsNull, values);
+    return new IntColumn(
+        arrayOffset + fromIndex,
+        positionCount - fromIndex,
+        valueIsNull,
+        values,
+        retainedSizeInBytes);
   }
 
   @Override
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/LongColumn.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/LongColumn.java
index b87b61d2b3..947e8d18fd 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/LongColumn.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/LongColumn.java
@@ -68,6 +68,19 @@ public class LongColumn implements Column {
     retainedSizeInBytes = INSTANCE_SIZE + sizeOf(valueIsNull) + sizeOf(values);
   }
 
+  LongColumn(
+      int arrayOffset,
+      int positionCount,
+      boolean[] valueIsNull,
+      long[] values,
+      long retainedSizeInBytes) {
+    this.arrayOffset = arrayOffset;
+    this.positionCount = positionCount;
+    this.values = values;
+    this.valueIsNull = valueIsNull;
+    this.retainedSizeInBytes = retainedSizeInBytes;
+  }
+
   @Override
   public TSDataType getDataType() {
     return TSDataType.INT64;
@@ -136,10 +149,12 @@ public class LongColumn implements Column {
 
   @Override
   public Column subColumn(int fromIndex) {
-    if (fromIndex > positionCount) {
-      throw new IllegalArgumentException("fromIndex is not valid");
-    }
-    return new LongColumn(arrayOffset + fromIndex, positionCount - fromIndex, valueIsNull, values);
+    return new LongColumn(
+        arrayOffset + fromIndex,
+        positionCount - fromIndex,
+        valueIsNull,
+        values,
+        retainedSizeInBytes);
   }
 
   @Override
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/NullColumn.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/NullColumn.java
index 29a9f8ae6b..1cb946197a 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/NullColumn.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/NullColumn.java
@@ -50,13 +50,7 @@ public class NullColumn implements Column {
   }
 
   public NullColumn(int arrayOffset, int positionCount) {
-    if (arrayOffset < 0) {
-      throw new IllegalArgumentException("arrayOffset is negative");
-    }
-    this.arrayOffset = positionCount;
-    if (positionCount < 0) {
-      throw new IllegalArgumentException("positionCount is negative");
-    }
+    this.arrayOffset = arrayOffset;
     this.positionCount = positionCount;
     retainedSizeInBytes = INSTANCE_SIZE;
   }
@@ -104,9 +98,6 @@ public class NullColumn implements Column {
 
   @Override
   public Column subColumn(int fromIndex) {
-    if (fromIndex > positionCount) {
-      throw new IllegalArgumentException("fromIndex is not valid");
-    }
     return new NullColumn(arrayOffset + fromIndex, positionCount - fromIndex);
   }
 
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/RunLengthEncodedColumn.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/RunLengthEncodedColumn.java
index b512b9f252..23c9e7a02d 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/RunLengthEncodedColumn.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/RunLengthEncodedColumn.java
@@ -198,9 +198,6 @@ public class RunLengthEncodedColumn implements Column {
 
   @Override
   public Column subColumn(int fromIndex) {
-    if (fromIndex > positionCount) {
-      throw new IllegalArgumentException("fromIndex is not valid");
-    }
     return new RunLengthEncodedColumn(value, positionCount - fromIndex);
   }
 
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/TimeColumn.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/TimeColumn.java
index df6232ed9f..348e8ec693 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/TimeColumn.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/block/column/TimeColumn.java
@@ -59,6 +59,13 @@ public class TimeColumn implements Column {
     retainedSizeInBytes = INSTANCE_SIZE + sizeOf(values);
   }
 
+  TimeColumn(int arrayOffset, int positionCount, long[] values, long retainedSizeInBytes) {
+    this.arrayOffset = arrayOffset;
+    this.positionCount = positionCount;
+    this.values = values;
+    this.retainedSizeInBytes = retainedSizeInBytes;
+  }
+
   @Override
   public TSDataType getDataType() {
     return TSDataType.INT64;
@@ -116,10 +123,8 @@ public class TimeColumn implements Column {
 
   @Override
   public Column subColumn(int fromIndex) {
-    if (fromIndex > positionCount) {
-      throw new IllegalArgumentException("fromIndex is not valid");
-    }
-    return new TimeColumn(arrayOffset + fromIndex, positionCount - fromIndex, values);
+    return new TimeColumn(
+        arrayOffset + fromIndex, positionCount - fromIndex, values, retainedSizeInBytes);
   }
 
   @Override
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/GroupByFilter.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/GroupByFilter.java
index 851d122bab..72ea2a9f92 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/GroupByFilter.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/filter/GroupByFilter.java
@@ -55,11 +55,7 @@ public class GroupByFilter implements Filter, Serializable {
 
   @Override
   public boolean satisfy(long time, Object value) {
-    if (time < startTime || time >= endTime) {
-      return false;
-    } else {
-      return (time - startTime) % slidingStep < interval;
-    }
+    return time >= startTime && time < endTime;
   }
 
   @Override
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/AlignedPageReader.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/AlignedPageReader.java
index 3f076906bb..360441f50e 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/AlignedPageReader.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/AlignedPageReader.java
@@ -39,7 +39,6 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 public class AlignedPageReader implements IPageReader, IAlignedPageReader {
@@ -114,80 +113,18 @@ public class AlignedPageReader implements IPageReader, IAlignedPageReader {
   }
 
   @Override
-  public TsBlock getAllSatisfiedData() throws IOException {
+  public TsBlock getAllSatisfiedData() {
     builder.reset();
-    long[] timeBatch = timePageReader.getNextTimeBatch();
+    int[] offsetAndLength =
+        timePageReader.nextSatisfiedTimeBatch(filter, builder.getTimeColumnBuilder());
 
-    // if all the sub sensors' value are null in current row, just discard it
-    // if !filter.satisfy, discard this row
-    boolean[] keepCurrentRow = new boolean[timeBatch.length];
-    if (filter == null) {
-      Arrays.fill(keepCurrentRow, true);
-    } else {
-      for (int i = 0, n = timeBatch.length; i < n; i++) {
-        keepCurrentRow[i] = filter.satisfy(timeBatch[i], null);
-      }
-    }
-
-    // using bitMap in valuePageReaders to indicate whether columns of current row are all null.
-    byte[] bitmask = new byte[(timeBatch.length - 1) / 8 + 1];
-    Arrays.fill(bitmask, (byte) 0x00);
-    boolean[][] isDeleted = new boolean[valueCount][timeBatch.length];
-    for (int columnIndex = 0; columnIndex < valueCount; columnIndex++) {
-      ValuePageReader pageReader = valuePageReaderList.get(columnIndex);
-      if (pageReader != null) {
-        byte[] bitmap = pageReader.getBitmap();
-        pageReader.fillIsDeleted(timeBatch, isDeleted[columnIndex]);
-
-        for (int i = 0, n = isDeleted[columnIndex].length; i < n; i++) {
-          if (isDeleted[columnIndex][i]) {
-            int shift = i % 8;
-            bitmap[i / 8] = (byte) (bitmap[i / 8] & (~(MASK >>> shift)));
-          }
-        }
-        for (int i = 0, n = bitmask.length; i < n; i++) {
-          bitmask[i] = (byte) (bitmap[i] | bitmask[i]);
-        }
-      }
-    }
-
-    for (int i = 0, n = bitmask.length; i < n; i++) {
-      if (bitmask[i] == (byte) 0xFF) {
-        // 8 rows are not all null, do nothing
-      } else if (bitmask[i] == (byte) 0x00) {
-        for (int j = 0; j < 8 && (i * 8 + j < keepCurrentRow.length); j++) {
-          keepCurrentRow[i * 8 + j] = false;
-        }
-      } else {
-        for (int j = 0; j < 8 && (i * 8 + j < keepCurrentRow.length); j++) {
-          if (((bitmask[i] & 0xFF) & (MASK >>> j)) == 0) {
-            keepCurrentRow[i * 8 + j] = false;
-          }
-        }
-      }
-    }
-
-    // construct time column
-    for (int i = 0; i < timeBatch.length; i++) {
-      if (keepCurrentRow[i]) {
-        builder.getTimeColumnBuilder().writeLong(timeBatch[i]);
-        builder.declarePosition();
-      }
-    }
+    builder.declarePositions(offsetAndLength[1]);
 
     // construct value columns
     for (int i = 0; i < valueCount; i++) {
       ValuePageReader pageReader = valuePageReaderList.get(i);
-      if (pageReader != null) {
-        pageReader.writeColumnBuilderWithNextBatch(
-            timeBatch, builder.getColumnBuilder(i), keepCurrentRow, isDeleted[i]);
-      } else {
-        for (int j = 0; j < timeBatch.length; j++) {
-          if (keepCurrentRow[j]) {
-            builder.getColumnBuilder(i).appendNull();
-          }
-        }
-      }
+      pageReader.writeColumnBuilderWithNextBatch(
+          offsetAndLength[0], offsetAndLength[1], builder.getColumnBuilder(i));
     }
     return builder.build();
   }
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/TimePageReader.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/TimePageReader.java
index fc05e2b0ba..362d8c54e8 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/TimePageReader.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/TimePageReader.java
@@ -22,6 +22,8 @@ import org.apache.iotdb.tsfile.encoding.decoder.Decoder;
 import org.apache.iotdb.tsfile.file.header.PageHeader;
 import org.apache.iotdb.tsfile.file.metadata.statistics.TimeStatistics;
 import org.apache.iotdb.tsfile.read.common.TimeRange;
+import org.apache.iotdb.tsfile.read.common.block.column.TimeColumnBuilder;
+import org.apache.iotdb.tsfile.read.filter.basic.Filter;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -86,6 +88,37 @@ public class TimePageReader {
     }
   }
 
+  /**
+   * In case that we use sequence read, and the page doesn't have statistics, so we won't know time
+   * array's length at first
+   */
+  public int[] nextSatisfiedTimeBatch(Filter timeFilter, TimeColumnBuilder timeColumnBuilder) {
+    if (timeFilter == null) {
+      for (int i = 0, size = (int) pageHeader.getStatistics().getCount(); i < size; i++) {
+        timeColumnBuilder.writeLong(timeDecoder.readLong(timeBuffer));
+      }
+      return new int[] {0, (int) pageHeader.getStatistics().getCount()};
+    } else {
+      int offset = 0, size = (int) pageHeader.getStatistics().getCount(), totalCount = 1;
+      long current = timeDecoder.readLong(timeBuffer);
+      while (!timeFilter.satisfy(current, null) && totalCount < size) {
+        current = timeDecoder.readLong(timeBuffer);
+        totalCount++;
+        offset++;
+      }
+      if (!timeFilter.satisfy(current, null)) {
+        return new int[] {size, 0};
+      }
+      timeColumnBuilder.writeLong(current);
+      while (totalCount < size
+          && timeFilter.satisfy(current = timeDecoder.readLong(timeBuffer), null)) {
+        timeColumnBuilder.writeLong(current);
+        totalCount++;
+      }
+      return new int[] {offset, totalCount - offset};
+    }
+  }
+
   public TimeStatistics getStatistics() {
     return (TimeStatistics) pageHeader.getStatistics();
   }
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/ValuePageReader.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/ValuePageReader.java
index 45729ec05e..4e70432858 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/ValuePageReader.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/reader/page/ValuePageReader.java
@@ -328,6 +328,135 @@ public class ValuePageReader {
     }
   }
 
+  public void writeColumnBuilderWithNextBatch(int offset, int length, ColumnBuilder columnBuilder) {
+    if (valueBuffer == null) {
+      for (int i = 0; i < length; i++) {
+        columnBuilder.appendNull();
+      }
+      return;
+    }
+
+    int i = 0;
+    switch (dataType) {
+      case BOOLEAN:
+        // skip offset
+        for (; i < offset; i++) {
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+
+          } else {
+            valueDecoder.readBoolean(valueBuffer);
+          }
+        }
+        // read length
+        for (; i < offset + length; i++) {
+          boolean aBoolean = valueDecoder.readBoolean(valueBuffer);
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+            columnBuilder.appendNull();
+          } else {
+            columnBuilder.writeBoolean(aBoolean);
+          }
+        }
+        break;
+      case INT32:
+        // skip offset
+        for (; i < offset; i++) {
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+
+          } else {
+            valueDecoder.readInt(valueBuffer);
+          }
+        }
+        // read length
+        for (; i < offset + length; i++) {
+          int anInt = valueDecoder.readInt(valueBuffer);
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+            columnBuilder.appendNull();
+          } else {
+            columnBuilder.writeInt(anInt);
+          }
+        }
+        break;
+      case INT64:
+        // skip offset
+        for (; i < offset; i++) {
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+
+          } else {
+            valueDecoder.readLong(valueBuffer);
+          }
+        }
+        // read length
+        for (; i < offset + length; i++) {
+          long aLong = valueDecoder.readLong(valueBuffer);
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+            columnBuilder.appendNull();
+          } else {
+            columnBuilder.writeLong(aLong);
+          }
+        }
+        break;
+      case FLOAT:
+        // skip offset
+        for (; i < offset; i++) {
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+
+          } else {
+            valueDecoder.readFloat(valueBuffer);
+          }
+        }
+        // read length
+        for (; i < offset + length; i++) {
+          float aFloat = valueDecoder.readFloat(valueBuffer);
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+            columnBuilder.appendNull();
+          } else {
+            columnBuilder.writeFloat(aFloat);
+          }
+        }
+        break;
+      case DOUBLE:
+        // skip offset
+        for (; i < offset; i++) {
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+
+          } else {
+            valueDecoder.readDouble(valueBuffer);
+          }
+        }
+        // read length
+        for (; i < offset + length; i++) {
+          double aDouble = valueDecoder.readDouble(valueBuffer);
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+            columnBuilder.appendNull();
+          } else {
+            columnBuilder.writeDouble(aDouble);
+          }
+        }
+        break;
+      case TEXT:
+        // skip offset
+        for (; i < offset; i++) {
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+
+          } else {
+            valueDecoder.readBinary(valueBuffer);
+          }
+        }
+        // read length
+        for (; i < offset + length; i++) {
+          Binary aBinary = valueDecoder.readBinary(valueBuffer);
+          if (((bitmap[i / 8] & 0xFF) & (MASK >>> (i % 8))) == 0) {
+            columnBuilder.appendNull();
+          } else {
+            columnBuilder.writeBinary(aBinary);
+          }
+        }
+        break;
+      default:
+        throw new UnSupportedDataTypeException(String.valueOf(dataType));
+    }
+  }
+
   public Statistics getStatistics() {
     return pageHeader.getStatistics();
   }