public void initChunkMetaFromTvLists() {
    // create chunk statistics
    Statistics<? extends Serializable> chunkStatistics = Statistics.getStatsByType(dataType);
    List<TVList> tvLists = new ArrayList<>(tvListQueryMap.keySet());
    timeValuePairIterator =
        MemPointIteratorFactory.create(
            dataType,
            tvLists,
            deletionList,
            floatPrecision,
            encoding,
            MAX_NUMBER_OF_POINTS_IN_PAGE);
    while (timeValuePairIterator.hasNextBatch()) {
      // statistics for current batch
      Statistics<? extends Serializable> pageStatistics = Statistics.getStatsByType(dataType);
      pageStatisticsList.add(pageStatistics);

      TsBlock tsBlock = timeValuePairIterator.nextBatch();
      if (!tsBlock.isEmpty()) {
        switch (dataType) {
          case BOOLEAN:
            for (int i = 0; i < tsBlock.getPositionCount(); i++) {
              long time = tsBlock.getTimeByIndex(i);
              chunkStatistics.update(time, tsBlock.getColumn(0).getBoolean(i));
              pageStatistics.update(time, tsBlock.getColumn(0).getBoolean(i));
            }
            break;
          case INT32:
          case DATE:
            for (int i = 0; i < tsBlock.getPositionCount(); i++) {
              long time = tsBlock.getTimeByIndex(i);
              chunkStatistics.update(time, tsBlock.getColumn(0).getInt(i));
              pageStatistics.update(time, tsBlock.getColumn(0).getInt(i));
            }
            break;
          case INT64:
          case TIMESTAMP:
            for (int i = 0; i < tsBlock.getPositionCount(); i++) {
              long time = tsBlock.getTimeByIndex(i);
              chunkStatistics.update(time, tsBlock.getColumn(0).getLong(i));
              pageStatistics.update(time, tsBlock.getColumn(0).getLong(i));
            }
            break;
          case FLOAT:
            for (int i = 0; i < tsBlock.getPositionCount(); i++) {
              long time = tsBlock.getTimeByIndex(i);
              chunkStatistics.update(time, tsBlock.getColumn(0).getFloat(i));
              pageStatistics.update(time, tsBlock.getColumn(0).getFloat(i));
            }
            break;
          case DOUBLE:
            for (int i = 0; i < tsBlock.getPositionCount(); i++) {
              long time = tsBlock.getTimeByIndex(i);
              chunkStatistics.update(time, tsBlock.getColumn(0).getDouble(i));
              pageStatistics.update(time, tsBlock.getColumn(0).getDouble(i));
            }
            break;
          case TEXT:
          case BLOB:
          case STRING:
            for (int i = 0; i < tsBlock.getPositionCount(); i++) {
              long time = tsBlock.getTimeByIndex(i);
              chunkStatistics.update(time, tsBlock.getColumn(0).getBinary(i));
              pageStatistics.update(time, tsBlock.getColumn(0).getBinary(i));
            }
            break;
          default:
            throw new UnSupportedDataTypeException(
                String.format("Data type %s is not supported.", dataType));
        }
      }
    }

    // chunk meta
    IChunkMetadata metaData =
        new ChunkMetadata(measurementUid, dataType, null, null, 0, chunkStatistics);
    metaData.setChunkLoader(new MemChunkLoader(context, this));
    metaData.setVersion(Long.MAX_VALUE);
    cachedMetaData = metaData;
  }
ReadOnlyMemChunk is a snapshot of the working MemTable and flushing memtable in the memory used
for querying.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/ReadOnlyMemChunk.java