public void queryForDeviceRegionScan(
      Map<IDeviceID, DeviceContext> devicePathsToContext,
      QueryContext queryContext,
      List<IFileScanHandle> fileScanHandlesForQuery) {
    long startTime = System.nanoTime();
    try {
      Map<IDeviceID, Map<String, List<IChunkHandle>>> deviceToMemChunkHandleMap = new HashMap<>();
      Map<IDeviceID, Map<String, List<IChunkMetadata>>> deviceToChunkMetadataListMap =
          new HashMap<>();
      flushQueryLock.readLock().lock();
      try {
        for (Map.Entry<IDeviceID, DeviceContext> entry : devicePathsToContext.entrySet()) {
          IDeviceID deviceID = entry.getKey();
          boolean isAligned = entry.getValue().isAligned();
          long timeLowerBound = getQueryTimeLowerBound(deviceID);
          Map<String, List<IChunkMetadata>> measurementToChunkMetadataList = new HashMap<>();
          Map<String, List<IChunkHandle>> measurementToMemChunkHandleList = new HashMap<>();
          for (IMemTable flushingMemTable : flushingMemTables) {
            if (flushingMemTable.isSignalMemTable()) {
              continue;
            }
            flushingMemTable.queryForDeviceRegionScan(
                deviceID,
                isAligned,
                timeLowerBound,
                measurementToChunkMetadataList,
                measurementToMemChunkHandleList,
                modsToMemtable);
          }
          if (workMemTable != null) {
            workMemTable.queryForDeviceRegionScan(
                deviceID,
                isAligned,
                timeLowerBound,
                measurementToChunkMetadataList,
                measurementToMemChunkHandleList,
                null);
          }

          buildChunkHandleForFlushedMemTable(
              deviceID,
              isAligned
                  ? getAlignedVisibleMetadataListFromWriterByDeviceID(queryContext, deviceID)
                  : getVisibleMetadataListFromWriterByDeviceID(queryContext, deviceID),
              measurementToChunkMetadataList,
              measurementToMemChunkHandleList);

          if (!measurementToMemChunkHandleList.isEmpty()
              || !measurementToChunkMetadataList.isEmpty()) {
            deviceToMemChunkHandleMap.put(deviceID, measurementToMemChunkHandleList);
            deviceToChunkMetadataListMap.put(deviceID, measurementToChunkMetadataList);
          }
        }
      } catch (QueryProcessException | MetadataException | IOException e) {
        logger.error(
            "{}: {} get ReadOnlyMemChunk has error",
            dataRegionName,
            tsFileResource.getTsFile().getName(),
            e);
      } finally {
        QUERY_RESOURCE_METRICS.recordQueryResourceNum(FLUSHING_MEMTABLE, flushingMemTables.size());
        QUERY_RESOURCE_METRICS.recordQueryResourceNum(
            WORKING_MEMTABLE, workMemTable != null ? 1 : 0);

        flushQueryLock.readLock().unlock();
        logFlushQueryReadUnlocked();
      }

      if (!deviceToMemChunkHandleMap.isEmpty() || !deviceToChunkMetadataListMap.isEmpty()) {
        fileScanHandlesForQuery.add(
            new UnclosedFileScanHandleImpl(
                deviceToChunkMetadataListMap, deviceToMemChunkHandleMap, tsFileResource));
      }
    } finally {
      QUERY_EXECUTION_METRICS.recordExecutionCost(
          GET_QUERY_RESOURCE_FROM_MEM, System.nanoTime() - startTime);
    }
  }
Construct IFileScanHandle for data in memtable and the other ones in flushing memtables. Then
get the related ChunkMetadata of data on disk.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/memtable/TsFileProcessor.java