You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ma...@apache.org on 2022/08/08 03:58:40 UTC

[iotdb] branch IOTDB-3455-O updated: remove RewriteCompactionFileSelector

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

marklau99 pushed a commit to branch IOTDB-3455-O
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/IOTDB-3455-O by this push:
     new 136418c75f remove RewriteCompactionFileSelector
136418c75f is described below

commit 136418c75fa53822fbf73ca284f966a196e2435b
Author: Liu Xuxin <li...@outlook.com>
AuthorDate: Mon Aug 8 11:58:29 2022 +0800

    remove RewriteCompactionFileSelector
---
 .../db/engine/compaction/CompactionUtils.java      |   16 -
 .../compaction/cross/CrossSpaceCompactionTask.java |    1 +
 .../RewriteCrossSpaceCompactionSelector.java       |  252 ++++-
 .../selector/RewriteCompactionFileSelector.java    |  285 ------
 .../cross/utils/InplaceCompactionEstimator.java    |    3 +-
 .../compaction/task/ICompactionSelector.java       |    4 +
 .../org/apache/iotdb/db/rescon/SystemInfo.java     |    8 +
 .../compaction/cross/CrossSpaceCompactionTest.java |   30 +-
 .../cross/CrossSpaceCompactionValidationTest.java  | 1072 ++++++++++----------
 .../engine/compaction/cross/MergeUpgradeTest.java  |   19 +-
 .../cross/RewriteCompactionFileSelectorTest.java   |  266 +++--
 11 files changed, 995 insertions(+), 961 deletions(-)

diff --git a/server/src/main/java/org/apache/iotdb/db/engine/compaction/CompactionUtils.java b/server/src/main/java/org/apache/iotdb/db/engine/compaction/CompactionUtils.java
index 23143a7b1d..5e5561b43e 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/compaction/CompactionUtils.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/compaction/CompactionUtils.java
@@ -20,10 +20,6 @@ package org.apache.iotdb.db.engine.compaction;
 
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.engine.compaction.constant.CrossCompactionSelector;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.CrossSpaceCompactionResource;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.ICrossSpaceCompactionFileSelector;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.RewriteCompactionFileSelector;
 import org.apache.iotdb.db.engine.modification.Modification;
 import org.apache.iotdb.db.engine.modification.ModificationFile;
 import org.apache.iotdb.db.engine.storagegroup.TsFileNameGenerator;
@@ -221,16 +217,4 @@ public class CompactionUtils {
       }
     }
   }
-
-  public static ICrossSpaceCompactionFileSelector getCrossSpaceFileSelector(
-      long budget, CrossSpaceCompactionResource resource) {
-    CrossCompactionSelector strategy =
-        IoTDBDescriptor.getInstance().getConfig().getCrossCompactionSelector();
-    switch (strategy) {
-      case REWRITE:
-        return new RewriteCompactionFileSelector(resource, budget);
-      default:
-        throw new UnsupportedOperationException("Unknown CrossSpaceFileStrategy " + strategy);
-    }
-  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionTask.java b/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionTask.java
index ab6725440e..cd0e1d7704 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionTask.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionTask.java
@@ -57,6 +57,7 @@ public class CrossSpaceCompactionTask extends AbstractCompactionTask {
   protected List<TsFileResource> holdReadLockList = new ArrayList<>();
   protected List<TsFileResource> holdWriteLockList = new ArrayList<>();
   protected long selectedFileSize = 0;
+  protected long memoryCost = 0L;
 
   public CrossSpaceCompactionTask(
       long timePartition,
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/rewrite/RewriteCrossSpaceCompactionSelector.java b/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/rewrite/RewriteCrossSpaceCompactionSelector.java
index 9cd31bba23..f6322cc536 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/rewrite/RewriteCrossSpaceCompactionSelector.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/rewrite/RewriteCrossSpaceCompactionSelector.java
@@ -22,9 +22,9 @@ import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.compaction.CompactionTaskManager;
-import org.apache.iotdb.db.engine.compaction.CompactionUtils;
 import org.apache.iotdb.db.engine.compaction.cross.ICrossSpaceSelector;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.ICrossSpaceCompactionFileSelector;
+import org.apache.iotdb.db.engine.compaction.cross.utils.AbstractCompactionEstimator;
+import org.apache.iotdb.db.engine.compaction.task.ICompactionSelector;
 import org.apache.iotdb.db.engine.storagegroup.TsFileManager;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.MergeException;
@@ -33,8 +33,11 @@ import org.apache.iotdb.tsfile.utils.Pair;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 
@@ -47,6 +50,22 @@ public class RewriteCrossSpaceCompactionSelector implements ICrossSpaceSelector
   protected long timePartition;
   protected TsFileManager tsFileManager;
 
+  private CrossSpaceCompactionResource resource;
+
+  private long totalCost;
+  private final long memoryBudget;
+  private final int maxCrossCompactionFileNum;
+
+  private List<TsFileResource> selectedUnseqFiles;
+  private List<TsFileResource> selectedSeqFiles;
+
+  private Collection<Integer> tmpSelectedSeqFiles;
+
+  private boolean[] seqSelected;
+  private int seqSelectedNum;
+
+  private AbstractCompactionEstimator compactionEstimator;
+
   public RewriteCrossSpaceCompactionSelector(
       String logicalStorageGroupName,
       String dataRegionId,
@@ -56,6 +75,223 @@ public class RewriteCrossSpaceCompactionSelector implements ICrossSpaceSelector
     this.dataRegionId = dataRegionId;
     this.timePartition = timePartition;
     this.tsFileManager = tsFileManager;
+    this.memoryBudget = config.getCrossCompactionMemoryBudget();
+    this.maxCrossCompactionFileNum =
+        IoTDBDescriptor.getInstance().getConfig().getMaxCrossCompactionCandidateFileNum();
+    this.compactionEstimator =
+        ICompactionSelector.getCompactionEstimator(
+            IoTDBDescriptor.getInstance().getConfig().getCrossCompactionPerformer(), false);
+  }
+
+  /**
+   * Select merge candidates from seqFiles and unseqFiles under the given memoryBudget. This process
+   * iteratively adds the next unseqFile from unseqFiles and its overlapping seqFiles as newly-added
+   * candidates and computes their estimated memory cost. If the current cost pluses the new cost is
+   * still under the budget, accept the unseqFile and the seqFiles as candidates, otherwise go to
+   * the next iteration. The memory cost of a file is calculated in two ways: The rough estimation:
+   * for a seqFile, the size of its metadata is used for estimation. Since in the worst case, the
+   * file only contains one timeseries and all its metadata will be loaded into memory with at most
+   * one actual data chunk (which is negligible) and writing the timeseries into a new file generate
+   * metadata of the similar size, so the size of all seqFiles' metadata (generated when writing new
+   * chunks) pluses the largest one (loaded when reading a timeseries from the seqFiles) is the
+   * total estimation of all seqFiles; for an unseqFile, since the merge reader may read all chunks
+   * of a series to perform a merge read, the whole file may be loaded into memory, so we use the
+   * file's length as the maximum estimation. The tight estimation: based on the rough estimation,
+   * we scan the file's metadata to count the number of chunks for each series, find the series
+   * which have the most chunks in the file and use its chunk proportion to refine the rough
+   * estimation. The rough estimation is performed first, if no candidates can be found using rough
+   * estimation, we run the selection again with tight estimation.
+   *
+   * @return two lists of TsFileResource, the former is selected seqFiles and the latter is selected
+   *     unseqFiles or an empty array if there are no proper candidates by the budget.
+   */
+  public List[] select() throws MergeException {
+    long startTime = System.currentTimeMillis();
+    try {
+      LOGGER.debug(
+          "Selecting merge candidates from {} seqFile, {} unseqFiles",
+          resource.getSeqFiles().size(),
+          resource.getUnseqFiles().size());
+      selectSourceFiles();
+      if (selectedUnseqFiles.isEmpty()) {
+        LOGGER.debug("No merge candidates are found");
+        return new List[0];
+      }
+    } catch (IOException e) {
+      throw new MergeException(e);
+    } finally {
+      try {
+        compactionEstimator.clear();
+      } catch (IOException e) {
+        throw new MergeException(e);
+      }
+    }
+    LOGGER.info(
+        "Selected merge candidates, {} seqFiles, {} unseqFiles, total memory cost {}, "
+            + "time consumption {}ms",
+        selectedSeqFiles.size(),
+        selectedUnseqFiles.size(),
+        totalCost,
+        System.currentTimeMillis() - startTime);
+
+    return new List[] {selectedSeqFiles, selectedUnseqFiles};
+  }
+
+  /**
+   * In a preset time (30 seconds), for each unseqFile, find the list of seqFiles that overlap with
+   * it and have not been selected by the file selector of this compaction task. After finding each
+   * unseqFile and its corresponding overlap seqFile list, estimate the additional memory overhead
+   * that may be added by compacting them (preferably using the loop estimate), and if it does not
+   * exceed the memory overhead preset by the system for the compaction thread, put them into the
+   * selectedSeqFiles and selectedUnseqFiles.
+   */
+  void selectSourceFiles() throws IOException {
+    tmpSelectedSeqFiles = new HashSet<>();
+    seqSelected = new boolean[resource.getSeqFiles().size()];
+    seqSelectedNum = 0;
+    selectedSeqFiles = new ArrayList<>();
+    selectedUnseqFiles = new ArrayList<>();
+
+    totalCost = 0;
+
+    int unseqIndex = 0;
+    long startTime = System.currentTimeMillis();
+    long timeConsumption = 0;
+    long timeLimit =
+        IoTDBDescriptor.getInstance().getConfig().getCrossCompactionFileSelectionTimeBudget();
+    if (timeLimit < 0) {
+      timeLimit = Long.MAX_VALUE;
+    }
+    while (unseqIndex < resource.getUnseqFiles().size() && timeConsumption < timeLimit) {
+      // select next unseq files
+      TsFileResource unseqFile = resource.getUnseqFiles().get(unseqIndex);
+      if (!unseqFile.getTsFile().exists() || unseqFile.isDeleted()) {
+        break;
+      }
+
+      if (seqSelectedNum != resource.getSeqFiles().size()) {
+        selectOverlappedSeqFiles(unseqFile);
+      }
+      boolean isSeqFilesValid = checkIsSeqFilesValid();
+      if (!isSeqFilesValid) {
+        tmpSelectedSeqFiles.clear();
+        break;
+      }
+
+      // Filter out the selected seq files
+      for (int i = 0; i < seqSelected.length; i++) {
+        if (seqSelected[i]) {
+          tmpSelectedSeqFiles.remove(i);
+        }
+      }
+
+      List<TsFileResource> tmpSelectedSeqFileResources = new ArrayList<>();
+      for (int seqIndex : tmpSelectedSeqFiles) {
+        tmpSelectedSeqFileResources.add(resource.getSeqFiles().get(seqIndex));
+      }
+      long newCost =
+          compactionEstimator.estimateCrossCompactionMemory(tmpSelectedSeqFileResources, unseqFile);
+      if (!updateSelectedFiles(newCost, unseqFile)) {
+        // older unseq files must be merged before newer ones
+        break;
+      }
+
+      tmpSelectedSeqFiles.clear();
+      unseqIndex++;
+      timeConsumption = System.currentTimeMillis() - startTime;
+    }
+    for (int i = 0; i < seqSelected.length; i++) {
+      if (seqSelected[i]) {
+        selectedSeqFiles.add(resource.getSeqFiles().get(i));
+      }
+    }
+  }
+
+  private boolean updateSelectedFiles(long newCost, TsFileResource unseqFile) {
+    if (selectedUnseqFiles.size() == 0
+        || (seqSelectedNum + selectedUnseqFiles.size() + 1 + tmpSelectedSeqFiles.size()
+                <= maxCrossCompactionFileNum
+            && totalCost + newCost < memoryBudget)) {
+      selectedUnseqFiles.add(unseqFile);
+
+      for (Integer seqIdx : tmpSelectedSeqFiles) {
+        if (!seqSelected[seqIdx]) {
+          seqSelectedNum++;
+          seqSelected[seqIdx] = true;
+        }
+      }
+      totalCost += newCost;
+      LOGGER.debug(
+          "Adding a new unseqFile {} and seqFiles {} as candidates, new cost {}, total"
+              + " cost {}",
+          unseqFile,
+          tmpSelectedSeqFiles,
+          newCost,
+          totalCost);
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * To avoid redundant data in seq files, cross space compaction should select all the seq files
+   * which have overlap with unseq files whether they are compacting or not. Therefore, before
+   * adding task into the queue, cross space compaction task should check whether source seq files
+   * are being compacted or not to speed up compaction.
+   */
+  private boolean checkIsSeqFilesValid() {
+    for (Integer seqIdx : tmpSelectedSeqFiles) {
+      if (resource.getSeqFiles().get(seqIdx).isCompactionCandidate()
+          || resource.getSeqFiles().get(seqIdx).isCompacting()
+          || !resource.getSeqFiles().get(seqIdx).isClosed()
+          || !resource.getSeqFiles().get(seqIdx).getTsFile().exists()) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Put the index of the seqFile that has an overlap with the specific unseqFile and has not been
+   * selected by the file selector of the compaction task into the tmpSelectedSeqFiles list. To
+   * determine whether overlap exists is to traverse each device ChunkGroup in unseqFiles, and
+   * determine whether it overlaps with the same device ChunkGroup of each seqFile that are not
+   * selected by the compaction task, if so, select this seqFile.
+   *
+   * @param unseqFile the tsFileResource of unseqFile to be compacted
+   */
+  private void selectOverlappedSeqFiles(TsFileResource unseqFile) {
+    for (String deviceId : unseqFile.getDevices()) {
+      long unseqStartTime = unseqFile.getStartTime(deviceId);
+      long unseqEndTime = unseqFile.getEndTime(deviceId);
+
+      boolean noMoreOverlap = false;
+      for (int i = 0; i < resource.getSeqFiles().size() && !noMoreOverlap; i++) {
+        TsFileResource seqFile = resource.getSeqFiles().get(i);
+        if (!seqFile.mayContainsDevice(deviceId)) {
+          continue;
+        }
+
+        long seqEndTime = seqFile.getEndTime(deviceId);
+        long seqStartTime = seqFile.getStartTime(deviceId);
+        if (!seqFile.isClosed()) {
+          // for unclosed file, only select those that overlap with the unseq file
+          if (unseqEndTime >= seqStartTime) {
+            tmpSelectedSeqFiles.add(i);
+          }
+        } else if (unseqEndTime <= seqEndTime) {
+          // if time range in unseq file is 10-20, seq file is 30-40, or
+          // time range in unseq file is 10-20, seq file is 15-25, then select this seq file and
+          // there is no more overlap later.
+          tmpSelectedSeqFiles.add(i);
+          noMoreOverlap = true;
+        } else if (unseqStartTime <= seqEndTime) {
+          // if time range in unseq file is 10-20, seq file is 0-15, then select this seq file and
+          // there may be overlap later.
+          tmpSelectedSeqFiles.add(i);
+        }
+      }
+    }
   }
 
   /**
@@ -88,13 +324,10 @@ public class RewriteCrossSpaceCompactionSelector implements ICrossSpaceSelector
     }
     long budget = config.getCrossCompactionMemoryBudget();
     long timeLowerBound = System.currentTimeMillis() - Long.MAX_VALUE;
-    CrossSpaceCompactionResource compactionResource =
-        new CrossSpaceCompactionResource(seqFileList, unSeqFileList, timeLowerBound);
+    this.resource = new CrossSpaceCompactionResource(seqFileList, unSeqFileList, timeLowerBound);
 
-    ICrossSpaceCompactionFileSelector fileSelector =
-        CompactionUtils.getCrossSpaceFileSelector(budget, compactionResource);
     try {
-      List[] mergeFiles = fileSelector.select();
+      List[] mergeFiles = select();
       if (mergeFiles.length == 0) {
         return Collections.emptyList();
       }
@@ -117,4 +350,9 @@ public class RewriteCrossSpaceCompactionSelector implements ICrossSpaceSelector
     }
     return Collections.emptyList();
   }
+
+  @Override
+  public long getSelectedFileMemoryCost() {
+    return totalCost;
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/rewrite/selector/RewriteCompactionFileSelector.java b/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/rewrite/selector/RewriteCompactionFileSelector.java
deleted file mode 100644
index e7ce60cb12..0000000000
--- a/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/rewrite/selector/RewriteCompactionFileSelector.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.iotdb.db.engine.compaction.cross.rewrite.selector;
-
-import org.apache.iotdb.commons.conf.IoTDBConstant;
-import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.CrossSpaceCompactionResource;
-import org.apache.iotdb.db.engine.compaction.cross.utils.AbstractCompactionEstimator;
-import org.apache.iotdb.db.engine.compaction.task.ICompactionSelector;
-import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
-import org.apache.iotdb.db.exception.MergeException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-
-/**
- * MaxFileMergeFileSelector selects the most files from given seqFiles and unseqFiles which can be
- * merged without exceeding given memory budget. It always assume the number of timeseries being
- * queried at the same time is 1 to maximize the number of file merged.
- */
-public class RewriteCompactionFileSelector implements ICrossSpaceCompactionFileSelector {
-  private static final Logger logger =
-      LoggerFactory.getLogger(IoTDBConstant.COMPACTION_LOGGER_NAME);
-
-  private final CrossSpaceCompactionResource resource;
-
-  private long totalCost;
-  private final long memoryBudget;
-  private final int maxCrossCompactionFileNum;
-
-  private List<TsFileResource> selectedUnseqFiles;
-  private List<TsFileResource> selectedSeqFiles;
-
-  private Collection<Integer> tmpSelectedSeqFiles;
-
-  private boolean[] seqSelected;
-  private int seqSelectedNum;
-
-  private AbstractCompactionEstimator compactionEstimator;
-
-  public RewriteCompactionFileSelector(CrossSpaceCompactionResource resource, long memoryBudget) {
-    this.resource = resource;
-    this.memoryBudget = memoryBudget;
-    this.maxCrossCompactionFileNum =
-        IoTDBDescriptor.getInstance().getConfig().getMaxCrossCompactionCandidateFileNum();
-    this.compactionEstimator =
-        ICompactionSelector.getCompactionEstimator(
-            IoTDBDescriptor.getInstance().getConfig().getCrossCompactionPerformer(), false);
-  }
-
-  /**
-   * Select merge candidates from seqFiles and unseqFiles under the given memoryBudget. This process
-   * iteratively adds the next unseqFile from unseqFiles and its overlapping seqFiles as newly-added
-   * candidates and computes their estimated memory cost. If the current cost pluses the new cost is
-   * still under the budget, accept the unseqFile and the seqFiles as candidates, otherwise go to
-   * the next iteration. The memory cost of a file is calculated in two ways: The rough estimation:
-   * for a seqFile, the size of its metadata is used for estimation. Since in the worst case, the
-   * file only contains one timeseries and all its metadata will be loaded into memory with at most
-   * one actual data chunk (which is negligible) and writing the timeseries into a new file generate
-   * metadata of the similar size, so the size of all seqFiles' metadata (generated when writing new
-   * chunks) pluses the largest one (loaded when reading a timeseries from the seqFiles) is the
-   * total estimation of all seqFiles; for an unseqFile, since the merge reader may read all chunks
-   * of a series to perform a merge read, the whole file may be loaded into memory, so we use the
-   * file's length as the maximum estimation. The tight estimation: based on the rough estimation,
-   * we scan the file's metadata to count the number of chunks for each series, find the series
-   * which have the most chunks in the file and use its chunk proportion to refine the rough
-   * estimation. The rough estimation is performed first, if no candidates can be found using rough
-   * estimation, we run the selection again with tight estimation.
-   *
-   * @return two lists of TsFileResource, the former is selected seqFiles and the latter is selected
-   *     unseqFiles or an empty array if there are no proper candidates by the budget.
-   */
-  @Override
-  public List[] select() throws MergeException {
-    long startTime = System.currentTimeMillis();
-    try {
-      logger.debug(
-          "Selecting merge candidates from {} seqFile, {} unseqFiles",
-          resource.getSeqFiles().size(),
-          resource.getUnseqFiles().size());
-      selectSourceFiles();
-      if (selectedUnseqFiles.isEmpty()) {
-        logger.debug("No merge candidates are found");
-        return new List[0];
-      }
-    } catch (IOException e) {
-      throw new MergeException(e);
-    } finally {
-      try {
-        compactionEstimator.clear();
-      } catch (IOException e) {
-        throw new MergeException(e);
-      }
-    }
-    logger.info(
-        "Selected merge candidates, {} seqFiles, {} unseqFiles, total memory cost {}, "
-            + "time consumption {}ms",
-        selectedSeqFiles.size(),
-        selectedUnseqFiles.size(),
-        totalCost,
-        System.currentTimeMillis() - startTime);
-
-    return new List[] {selectedSeqFiles, selectedUnseqFiles};
-  }
-
-  /**
-   * In a preset time (30 seconds), for each unseqFile, find the list of seqFiles that overlap with
-   * it and have not been selected by the file selector of this compaction task. After finding each
-   * unseqFile and its corresponding overlap seqFile list, estimate the additional memory overhead
-   * that may be added by compacting them (preferably using the loop estimate), and if it does not
-   * exceed the memory overhead preset by the system for the compaction thread, put them into the
-   * selectedSeqFiles and selectedUnseqFiles.
-   */
-  void selectSourceFiles() throws IOException {
-    tmpSelectedSeqFiles = new HashSet<>();
-    seqSelected = new boolean[resource.getSeqFiles().size()];
-    seqSelectedNum = 0;
-    selectedSeqFiles = new ArrayList<>();
-    selectedUnseqFiles = new ArrayList<>();
-
-    totalCost = 0;
-
-    int unseqIndex = 0;
-    long startTime = System.currentTimeMillis();
-    long timeConsumption = 0;
-    long timeLimit =
-        IoTDBDescriptor.getInstance().getConfig().getCrossCompactionFileSelectionTimeBudget();
-    if (timeLimit < 0) {
-      timeLimit = Long.MAX_VALUE;
-    }
-    while (unseqIndex < resource.getUnseqFiles().size() && timeConsumption < timeLimit) {
-      // select next unseq files
-      TsFileResource unseqFile = resource.getUnseqFiles().get(unseqIndex);
-      if (!unseqFile.getTsFile().exists() || unseqFile.isDeleted()) {
-        break;
-      }
-
-      if (seqSelectedNum != resource.getSeqFiles().size()) {
-        selectOverlappedSeqFiles(unseqFile);
-      }
-      boolean isSeqFilesValid = checkIsSeqFilesValid();
-      if (!isSeqFilesValid) {
-        tmpSelectedSeqFiles.clear();
-        break;
-      }
-
-      // Filter out the selected seq files
-      for (int i = 0; i < seqSelected.length; i++) {
-        if (seqSelected[i]) {
-          tmpSelectedSeqFiles.remove(i);
-        }
-      }
-
-      List<TsFileResource> tmpSelectedSeqFileResources = new ArrayList<>();
-      for (int seqIndex : tmpSelectedSeqFiles) {
-        tmpSelectedSeqFileResources.add(resource.getSeqFiles().get(seqIndex));
-      }
-      long newCost =
-          compactionEstimator.estimateCrossCompactionMemory(tmpSelectedSeqFileResources, unseqFile);
-      if (!updateSelectedFiles(newCost, unseqFile)) {
-        // older unseq files must be merged before newer ones
-        break;
-      }
-
-      tmpSelectedSeqFiles.clear();
-      unseqIndex++;
-      timeConsumption = System.currentTimeMillis() - startTime;
-    }
-    for (int i = 0; i < seqSelected.length; i++) {
-      if (seqSelected[i]) {
-        selectedSeqFiles.add(resource.getSeqFiles().get(i));
-      }
-    }
-  }
-
-  private boolean updateSelectedFiles(long newCost, TsFileResource unseqFile) {
-    if (selectedUnseqFiles.size() == 0
-        || (seqSelectedNum + selectedUnseqFiles.size() + 1 + tmpSelectedSeqFiles.size()
-                <= maxCrossCompactionFileNum
-            && totalCost + newCost < memoryBudget)) {
-      selectedUnseqFiles.add(unseqFile);
-
-      for (Integer seqIdx : tmpSelectedSeqFiles) {
-        if (!seqSelected[seqIdx]) {
-          seqSelectedNum++;
-          seqSelected[seqIdx] = true;
-        }
-      }
-      totalCost += newCost;
-      logger.debug(
-          "Adding a new unseqFile {} and seqFiles {} as candidates, new cost {}, total"
-              + " cost {}",
-          unseqFile,
-          tmpSelectedSeqFiles,
-          newCost,
-          totalCost);
-      return true;
-    }
-    return false;
-  }
-
-  /**
-   * To avoid redundant data in seq files, cross space compaction should select all the seq files
-   * which have overlap with unseq files whether they are compacting or not. Therefore, before
-   * adding task into the queue, cross space compaction task should check whether source seq files
-   * are being compacted or not to speed up compaction.
-   */
-  private boolean checkIsSeqFilesValid() {
-    for (Integer seqIdx : tmpSelectedSeqFiles) {
-      if (resource.getSeqFiles().get(seqIdx).isCompactionCandidate()
-          || resource.getSeqFiles().get(seqIdx).isCompacting()
-          || !resource.getSeqFiles().get(seqIdx).isClosed()
-          || !resource.getSeqFiles().get(seqIdx).getTsFile().exists()) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  /**
-   * Put the index of the seqFile that has an overlap with the specific unseqFile and has not been
-   * selected by the file selector of the compaction task into the tmpSelectedSeqFiles list. To
-   * determine whether overlap exists is to traverse each device ChunkGroup in unseqFiles, and
-   * determine whether it overlaps with the same device ChunkGroup of each seqFile that are not
-   * selected by the compaction task, if so, select this seqFile.
-   *
-   * @param unseqFile the tsFileResource of unseqFile to be compacted
-   */
-  private void selectOverlappedSeqFiles(TsFileResource unseqFile) {
-    for (String deviceId : unseqFile.getDevices()) {
-      long unseqStartTime = unseqFile.getStartTime(deviceId);
-      long unseqEndTime = unseqFile.getEndTime(deviceId);
-
-      boolean noMoreOverlap = false;
-      for (int i = 0; i < resource.getSeqFiles().size() && !noMoreOverlap; i++) {
-        TsFileResource seqFile = resource.getSeqFiles().get(i);
-        if (!seqFile.mayContainsDevice(deviceId)) {
-          continue;
-        }
-
-        long seqEndTime = seqFile.getEndTime(deviceId);
-        long seqStartTime = seqFile.getStartTime(deviceId);
-        if (!seqFile.isClosed()) {
-          // for unclosed file, only select those that overlap with the unseq file
-          if (unseqEndTime >= seqStartTime) {
-            tmpSelectedSeqFiles.add(i);
-          }
-        } else if (unseqEndTime <= seqEndTime) {
-          // if time range in unseq file is 10-20, seq file is 30-40, or
-          // time range in unseq file is 10-20, seq file is 15-25, then select this seq file and
-          // there is no more overlap later.
-          tmpSelectedSeqFiles.add(i);
-          noMoreOverlap = true;
-        } else if (unseqStartTime <= seqEndTime) {
-          // if time range in unseq file is 10-20, seq file is 0-15, then select this seq file and
-          // there may be overlap later.
-          tmpSelectedSeqFiles.add(i);
-        }
-      }
-    }
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/utils/InplaceCompactionEstimator.java b/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/utils/InplaceCompactionEstimator.java
index 5f195db339..9032c5d9e7 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/utils/InplaceCompactionEstimator.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/compaction/cross/utils/InplaceCompactionEstimator.java
@@ -20,7 +20,6 @@ package org.apache.iotdb.db.engine.compaction.cross.utils;
 
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.compaction.cross.AbstractCrossSpaceEstimator;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.RewriteCompactionFileSelector;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.tsfile.file.metadata.ChunkMetadata;
 import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
@@ -35,7 +34,7 @@ import java.util.List;
 import java.util.Map;
 
 public class InplaceCompactionEstimator extends AbstractCrossSpaceEstimator {
-  private static final Logger logger = LoggerFactory.getLogger(RewriteCompactionFileSelector.class);
+  private static final Logger logger = LoggerFactory.getLogger(InplaceCompactionEstimator.class);
   private static final String LOG_FILE_COST = "Memory cost of file {} is {}";
 
   private boolean tightEstimate;
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/compaction/task/ICompactionSelector.java b/server/src/main/java/org/apache/iotdb/db/engine/compaction/task/ICompactionSelector.java
index 72063d5578..95a5f88d6c 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/compaction/task/ICompactionSelector.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/compaction/task/ICompactionSelector.java
@@ -55,6 +55,10 @@ public interface ICompactionSelector {
     }
   }
 
+  default long getSelectedFileMemoryCost() {
+    return 0L;
+  }
+
   static AbstractCompactionEstimator getCompactionEstimator(
       CrossCompactionPerformer compactionPerformer, boolean isInnerSpace) {
     switch (compactionPerformer) {
diff --git a/server/src/main/java/org/apache/iotdb/db/rescon/SystemInfo.java b/server/src/main/java/org/apache/iotdb/db/rescon/SystemInfo.java
index 09e432bec2..7e015d1f7a 100644
--- a/server/src/main/java/org/apache/iotdb/db/rescon/SystemInfo.java
+++ b/server/src/main/java/org/apache/iotdb/db/rescon/SystemInfo.java
@@ -170,6 +170,14 @@ public class SystemInfo {
     this.flushingMemTablesCost -= flushingMemTableCost;
   }
 
+  public synchronized void addCompactionMemoryCost(long compactionMemoryCost) {
+    this.totalStorageGroupMemCost += compactionMemoryCost;
+  }
+
+  public synchronized void resetCompactionMemoryCost(long compactionMemoryCost) {
+    this.totalStorageGroupMemCost -= compactionMemoryCost;
+  }
+
   private void logCurrentTotalSGMemory() {
     logger.debug("Current Sg cost is {}", totalStorageGroupMemCost);
   }
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionTest.java b/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionTest.java
index 766352659e..554c1d8181 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionTest.java
@@ -26,8 +26,7 @@ import org.apache.iotdb.db.engine.cache.ChunkCache;
 import org.apache.iotdb.db.engine.cache.TimeSeriesMetadataCache;
 import org.apache.iotdb.db.engine.compaction.CompactionTaskManager;
 import org.apache.iotdb.db.engine.compaction.cross.rewrite.CrossSpaceCompactionResource;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.ICrossSpaceCompactionFileSelector;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.RewriteCompactionFileSelector;
+import org.apache.iotdb.db.engine.compaction.cross.rewrite.RewriteCrossSpaceCompactionSelector;
 import org.apache.iotdb.db.engine.compaction.task.AbstractCompactionTask;
 import org.apache.iotdb.db.engine.compaction.utils.CompactionCheckerUtils;
 import org.apache.iotdb.db.engine.compaction.utils.CompactionClearUtils;
@@ -423,11 +422,12 @@ public class CrossSpaceCompactionTest {
           CrossSpaceCompactionResource mergeResource =
               new CrossSpaceCompactionResource(
                   seqTsFileResourceList, unseqTsFileResourceList, timeLowerBound);
-          ICrossSpaceCompactionFileSelector fileSelector =
-              new RewriteCompactionFileSelector(mergeResource, Long.MAX_VALUE);
-          List[] mergeFiles = fileSelector.select();
+          RewriteCrossSpaceCompactionSelector selector =
+              new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+          List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+              selector.selectCrossSpaceTask(seqTsFileResourceList, unseqTsFileResourceList);
           index++;
-          if (mergeFiles.length > 0) {
+          if (selected.size() > 0) {
             AbstractCompactionTask compactionTask =
                 new CrossSpaceCompactionTask(
                     0,
@@ -729,10 +729,11 @@ public class CrossSpaceCompactionTest {
           CrossSpaceCompactionResource mergeResource =
               new CrossSpaceCompactionResource(
                   seqTsFileResourceList, unseqTsFileResourceList, timeLowerBound);
-          ICrossSpaceCompactionFileSelector fileSelector =
-              new RewriteCompactionFileSelector(mergeResource, Long.MAX_VALUE);
-          List[] mergeFiles = fileSelector.select();
-          if (mergeFiles.length > 0) {
+          RewriteCrossSpaceCompactionSelector selector =
+              new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+          List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+              selector.selectCrossSpaceTask(seqTsFileResourceList, unseqTsFileResourceList);
+          if (selected.size() > 0) {
             AbstractCompactionTask compactionTask =
                 new CrossSpaceCompactionTask(
                     0,
@@ -1033,10 +1034,11 @@ public class CrossSpaceCompactionTest {
           CrossSpaceCompactionResource mergeResource =
               new CrossSpaceCompactionResource(
                   seqTsFileResourceList, unseqTsFileResourceList, timeLowerBound);
-          ICrossSpaceCompactionFileSelector fileSelector =
-              new RewriteCompactionFileSelector(mergeResource, Long.MAX_VALUE);
-          List[] mergeFiles = fileSelector.select();
-          if (mergeFiles.length > 0) {
+          RewriteCrossSpaceCompactionSelector selector =
+              new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+          List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+              selector.selectCrossSpaceTask(seqTsFileResourceList, unseqTsFileResourceList);
+          if (selected.size() > 0) {
             AbstractCompactionTask compactionTask =
                 new CrossSpaceCompactionTask(
                     0,
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionValidationTest.java b/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionValidationTest.java
index 98c1419389..d275dd9dd4 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionValidationTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/CrossSpaceCompactionValidationTest.java
@@ -23,8 +23,7 @@ import org.apache.iotdb.commons.exception.MetadataException;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.compaction.AbstractCompactionTest;
 import org.apache.iotdb.db.engine.compaction.cross.rewrite.CrossSpaceCompactionResource;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.ICrossSpaceCompactionFileSelector;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.RewriteCompactionFileSelector;
+import org.apache.iotdb.db.engine.compaction.cross.rewrite.RewriteCrossSpaceCompactionSelector;
 import org.apache.iotdb.db.engine.storagegroup.TsFileManager;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResourceStatus;
@@ -34,6 +33,7 @@ import org.apache.iotdb.db.query.control.FileReaderManager;
 import org.apache.iotdb.db.tools.validate.TsFileValidationTool;
 import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
 import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
+import org.apache.iotdb.tsfile.utils.Pair;
 
 import org.junit.After;
 import org.junit.Assert;
@@ -83,24 +83,22 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
     tsFileManager.addAll(seqResources, true);
     tsFileManager.addAll(unseqResources, false);
 
-    CrossSpaceCompactionResource resource =
-        new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(1, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+    Assert.assertEquals(1, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
 
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -130,23 +128,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(1, result[0].size());
-    Assert.assertEquals(2, result[1].size());
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
 
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
+    Assert.assertEquals(1, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
 
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -176,23 +175,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -228,25 +228,26 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(4, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
-
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
-    Assert.assertEquals(result[1].get(2), unseqResources.get(2));
-    Assert.assertEquals(result[1].get(3), unseqResources.get(3));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(4, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
+    Assert.assertEquals(selected.get(0).right.get(2), unseqResources.get(2));
+    Assert.assertEquals(selected.get(0).right.get(3), unseqResources.get(3));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -278,26 +279,27 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(5, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
-    Assert.assertEquals(result[0].get(2), seqResources.get(3));
-    Assert.assertEquals(result[0].get(3), seqResources.get(4));
-    Assert.assertEquals(result[0].get(4), seqResources.get(5));
-
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(5, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).left.get(3), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).left.get(4), seqResources.get(5));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -329,24 +331,25 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(1, result[0].size());
-    Assert.assertEquals(3, result[1].size());
-    for (TsFileResource selectedResource : (List<TsFileResource>) result[0]) {
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(1, selected.get(0).left.size());
+    Assert.assertEquals(3, selected.get(0).right.size());
+    for (TsFileResource selectedResource : (List<TsFileResource>) selected.get(0).left) {
       Assert.assertEquals(selectedResource, seqResources.get(1));
     }
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
-    Assert.assertEquals(result[1].get(2), unseqResources.get(2));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
+    Assert.assertEquals(selected.get(0).right.get(2), unseqResources.get(2));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -379,26 +382,27 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(3, result[0].size());
-    Assert.assertEquals(4, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
-    Assert.assertEquals(result[0].get(2), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
-    Assert.assertEquals(result[1].get(2), unseqResources.get(2));
-    Assert.assertEquals(result[1].get(3), unseqResources.get(3));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(3, selected.get(0).left.size());
+    Assert.assertEquals(4, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
+    Assert.assertEquals(selected.get(0).right.get(2), unseqResources.get(2));
+    Assert.assertEquals(selected.get(0).right.get(3), unseqResources.get(3));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -430,26 +434,27 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(4, result[1].size());
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
 
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(4, selected.get(0).right.size());
 
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
-    Assert.assertEquals(result[1].get(2), unseqResources.get(2));
-    Assert.assertEquals(result[1].get(3), unseqResources.get(3));
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
+    Assert.assertEquals(selected.get(0).right.get(2), unseqResources.get(2));
+    Assert.assertEquals(selected.get(0).right.get(3), unseqResources.get(3));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -484,23 +489,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -536,23 +542,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -589,22 +596,23 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(4));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -640,23 +648,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -693,23 +702,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -747,23 +757,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(4));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -800,24 +811,25 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(3, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
-    Assert.assertEquals(result[0].get(2), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(3, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -855,24 +867,25 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(3, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
-    Assert.assertEquals(result[0].get(2), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(3, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -911,24 +924,25 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(3, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
-    Assert.assertEquals(result[0].get(2), seqResources.get(4));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(3, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -966,25 +980,26 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(5, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[0].get(2), seqResources.get(4));
-    Assert.assertEquals(result[0].get(3), seqResources.get(5));
-    Assert.assertEquals(result[0].get(4), seqResources.get(6));
-
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(5, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).left.get(3), seqResources.get(5));
+    Assert.assertEquals(selected.get(0).left.get(4), seqResources.get(6));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1022,25 +1037,26 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(5, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[0].get(2), seqResources.get(4));
-    Assert.assertEquals(result[0].get(3), seqResources.get(5));
-    Assert.assertEquals(result[0].get(4), seqResources.get(6));
-
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(5, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).left.get(3), seqResources.get(5));
+    Assert.assertEquals(selected.get(0).left.get(4), seqResources.get(6));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1078,25 +1094,26 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(6, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[0].get(2), seqResources.get(4));
-    Assert.assertEquals(result[0].get(3), seqResources.get(5));
-    Assert.assertEquals(result[0].get(4), seqResources.get(6));
-    Assert.assertEquals(result[0].get(5), seqResources.get(7));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(6, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).left.get(3), seqResources.get(5));
+    Assert.assertEquals(selected.get(0).left.get(4), seqResources.get(6));
+    Assert.assertEquals(selected.get(0).left.get(5), seqResources.get(7));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1134,24 +1151,25 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(5, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[0].get(2), seqResources.get(4));
-    Assert.assertEquals(result[0].get(3), seqResources.get(5));
-    Assert.assertEquals(result[0].get(4), seqResources.get(7));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(5, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).left.get(3), seqResources.get(5));
+    Assert.assertEquals(selected.get(0).left.get(4), seqResources.get(7));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1186,23 +1204,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1238,23 +1257,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1291,22 +1311,23 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(4));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1342,23 +1363,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1395,23 +1417,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1449,23 +1472,24 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(4));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1502,24 +1526,25 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(3, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
-    Assert.assertEquals(result[0].get(2), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(3, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1557,24 +1582,25 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(3, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
-    Assert.assertEquals(result[0].get(2), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(3, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1613,24 +1639,25 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(3, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-
-    Assert.assertEquals(result[0].get(0), seqResources.get(1));
-    Assert.assertEquals(result[0].get(1), seqResources.get(2));
-    Assert.assertEquals(result[0].get(2), seqResources.get(4));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(3, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(1));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1668,25 +1695,26 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(5, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[0].get(2), seqResources.get(4));
-    Assert.assertEquals(result[0].get(3), seqResources.get(5));
-    Assert.assertEquals(result[0].get(4), seqResources.get(6));
-
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(5, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).left.get(3), seqResources.get(5));
+    Assert.assertEquals(selected.get(0).left.get(4), seqResources.get(6));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1724,25 +1752,26 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(5, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[0].get(2), seqResources.get(4));
-    Assert.assertEquals(result[0].get(3), seqResources.get(5));
-    Assert.assertEquals(result[0].get(4), seqResources.get(6));
-
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(5, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).left.get(3), seqResources.get(5));
+    Assert.assertEquals(selected.get(0).left.get(4), seqResources.get(6));
+
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1780,25 +1809,26 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(6, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[0].get(2), seqResources.get(4));
-    Assert.assertEquals(result[0].get(3), seqResources.get(5));
-    Assert.assertEquals(result[0].get(4), seqResources.get(6));
-    Assert.assertEquals(result[0].get(5), seqResources.get(7));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(6, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).left.get(3), seqResources.get(5));
+    Assert.assertEquals(selected.get(0).left.get(4), seqResources.get(6));
+    Assert.assertEquals(selected.get(0).left.get(5), seqResources.get(7));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1836,24 +1866,25 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(5, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[0].get(2), seqResources.get(4));
-    Assert.assertEquals(result[0].get(3), seqResources.get(5));
-    Assert.assertEquals(result[0].get(4), seqResources.get(7));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(5, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).left.get(2), seqResources.get(4));
+    Assert.assertEquals(selected.get(0).left.get(3), seqResources.get(5));
+    Assert.assertEquals(selected.get(0).left.get(4), seqResources.get(7));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1892,21 +1923,22 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1947,15 +1979,16 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
     // Assert.assertEquals(0, result.length);
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -1995,21 +2028,22 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -2049,22 +2083,23 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
-    Assert.assertEquals(result[1].get(1), unseqResources.get(1));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(2, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
+    Assert.assertEquals(selected.get(0).right.get(1), unseqResources.get(1));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
@@ -2105,21 +2140,22 @@ public class CrossSpaceCompactionValidationTest extends AbstractCompactionTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(1, result[1].size());
-    Assert.assertEquals(result[0].get(0), seqResources.get(2));
-    Assert.assertEquals(result[0].get(1), seqResources.get(3));
-    Assert.assertEquals(result[1].get(0), unseqResources.get(0));
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+
+    Assert.assertEquals(2, selected.get(0).left.size());
+    Assert.assertEquals(1, selected.get(0).right.size());
+    Assert.assertEquals(selected.get(0).left.get(0), seqResources.get(2));
+    Assert.assertEquals(selected.get(0).left.get(1), seqResources.get(3));
+    Assert.assertEquals(selected.get(0).right.get(0), unseqResources.get(0));
 
     new CrossSpaceCompactionTask(
             0,
             tsFileManager,
-            result[0],
-            result[1],
+            selected.get(0).left,
+            selected.get(0).right,
             IoTDBDescriptor.getInstance()
                 .getConfig()
                 .getCrossCompactionPerformer()
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/MergeUpgradeTest.java b/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/MergeUpgradeTest.java
index 6e81c159b5..559abd7a12 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/MergeUpgradeTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/MergeUpgradeTest.java
@@ -21,9 +21,9 @@ package org.apache.iotdb.db.engine.compaction.cross;
 
 import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.db.constant.TestConstant;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.CrossSpaceCompactionResource;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.RewriteCompactionFileSelector;
+import org.apache.iotdb.db.engine.compaction.cross.rewrite.RewriteCrossSpaceCompactionSelector;
 import org.apache.iotdb.db.engine.compaction.utils.CompactionConfigRestorer;
+import org.apache.iotdb.db.engine.storagegroup.TsFileManager;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.MergeException;
 import org.apache.iotdb.tsfile.common.conf.TSFileConfig;
@@ -33,6 +33,7 @@ import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 import org.apache.iotdb.tsfile.fileSystem.FSFactoryProducer;
 import org.apache.iotdb.tsfile.read.common.Path;
+import org.apache.iotdb.tsfile.utils.Pair;
 import org.apache.iotdb.tsfile.write.TsFileWriter;
 import org.apache.iotdb.tsfile.write.record.TSRecord;
 import org.apache.iotdb.tsfile.write.record.datapoint.DataPoint;
@@ -79,12 +80,14 @@ public class MergeUpgradeTest {
 
   @Test
   public void testMergeUpgradeSelect() throws MergeException {
-    CrossSpaceCompactionResource resource =
-        new CrossSpaceCompactionResource(seqResources, unseqResources);
-    RewriteCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    assertEquals(0, result.length);
+    TsFileManager tsFileManager = new TsFileManager("", "", "");
+    tsFileManager.addAll(seqResources, true);
+    tsFileManager.addAll(unseqResources, true);
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, tsFileManager);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+    assertEquals(0, selected.size());
   }
 
   private void prepareFiles() throws IOException, WriteProcessException {
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/RewriteCompactionFileSelectorTest.java b/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/RewriteCompactionFileSelectorTest.java
index 2b9a9d0fd4..f1dff5e9a0 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/RewriteCompactionFileSelectorTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/compaction/cross/RewriteCompactionFileSelectorTest.java
@@ -23,14 +23,14 @@ import org.apache.iotdb.commons.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.constant.TestConstant;
 import org.apache.iotdb.db.engine.compaction.cross.rewrite.CrossSpaceCompactionResource;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.ICrossSpaceCompactionFileSelector;
-import org.apache.iotdb.db.engine.compaction.cross.rewrite.selector.RewriteCompactionFileSelector;
+import org.apache.iotdb.db.engine.compaction.cross.rewrite.RewriteCrossSpaceCompactionSelector;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResourceStatus;
 import org.apache.iotdb.db.engine.storagegroup.timeindex.ITimeIndex;
 import org.apache.iotdb.db.exception.MergeException;
 import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
 import org.apache.iotdb.tsfile.read.common.Path;
+import org.apache.iotdb.tsfile.utils.Pair;
 import org.apache.iotdb.tsfile.write.TsFileWriter;
 import org.apache.iotdb.tsfile.write.record.TSRecord;
 import org.apache.iotdb.tsfile.write.record.datapoint.DataPoint;
@@ -51,7 +51,6 @@ import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
 
 public class RewriteCompactionFileSelectorTest extends MergeTest {
   private static final Logger logger =
@@ -59,29 +58,26 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
 
   @Test
   public void testFullSelection() throws MergeException, IOException {
-    CrossSpaceCompactionResource resource =
-        new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    List<TsFileResource> seqSelected = result[0];
-    List<TsFileResource> unseqSelected = result[1];
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+    List<TsFileResource> seqSelected = selected.get(0).left;
+    List<TsFileResource> unseqSelected = selected.get(0).right;
     assertEquals(seqResources, seqSelected);
     assertEquals(unseqResources, unseqSelected);
 
-    resource = new CrossSpaceCompactionResource(seqResources.subList(0, 1), unseqResources);
-    mergeFileSelector = new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    result = mergeFileSelector.select();
-    seqSelected = result[0];
-    unseqSelected = result[1];
+    selector = new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    selected = selector.selectCrossSpaceTask(seqResources.subList(0, 1), unseqResources);
+    seqSelected = selected.get(0).left;
+    unseqSelected = selected.get(0).right;
     assertEquals(seqResources.subList(0, 1), seqSelected);
     assertEquals(unseqResources, unseqSelected);
 
-    resource = new CrossSpaceCompactionResource(seqResources, unseqResources.subList(0, 1));
-    mergeFileSelector = new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    result = mergeFileSelector.select();
-    seqSelected = result[0];
-    unseqSelected = result[1];
+    selector = new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    selected = selector.selectCrossSpaceTask(seqResources, unseqResources.subList(0, 1));
+    seqSelected = selected.get(0).left;
+    unseqSelected = selected.get(0).right;
     assertEquals(seqResources.subList(0, 1), seqSelected);
     assertEquals(unseqResources.subList(0, 1), unseqSelected);
   }
@@ -90,21 +86,23 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
   public void testWithFewMemoryBudgeSelection() throws MergeException, IOException {
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, 1);
-    List[] result = mergeFileSelector.select();
-    assertEquals(2, result.length);
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+    assertEquals(1, selected.size());
   }
 
   @Test
   public void testRestrictedSelection() throws MergeException, IOException {
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, 400000);
-    List[] result = mergeFileSelector.select();
-    List<TsFileResource> seqSelected = result[0];
-    List<TsFileResource> unseqSelected = result[1];
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+    List<TsFileResource> seqSelected = selected.get(0).left;
+    List<TsFileResource> unseqSelected = selected.get(0).right;
     assertEquals(seqResources.subList(0, 5), seqSelected);
     assertEquals(unseqResources.subList(0, 6), unseqSelected);
   }
@@ -155,12 +153,11 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
 
     List<TsFileResource> newUnseqResources = new ArrayList<>();
     newUnseqResources.add(largeUnseqTsFileResource);
-    CrossSpaceCompactionResource resource =
-        new CrossSpaceCompactionResource(seqResources, newUnseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    assertEquals(0, result.length);
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, newUnseqResources);
+    assertEquals(0, selected.size());
   }
 
   /**
@@ -247,10 +244,11 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
 
     CrossSpaceCompactionResource resource =
         new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    assertEquals(2, result[0].size());
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+    assertEquals(2, selected.get(0).left.size());
   }
 
   @Test
@@ -305,21 +303,28 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
       CrossSpaceCompactionResource resource = new CrossSpaceCompactionResource(seqList, unseqList);
       // the budget is enough to select unseq0 and unseq2, but not unseq1
       // the first selection should only contain seq0 and unseq0
-      ICrossSpaceCompactionFileSelector mergeFileSelector =
-          new RewriteCompactionFileSelector(resource, 29000);
-      List[] result = mergeFileSelector.select();
-      assertEquals(1, result[0].size());
-      assertEquals(1, result[1].size());
-      assertEquals(seqList.get(0), result[0].get(0));
-      assertEquals(unseqList.get(0), result[1].get(0));
-
-      resource =
-          new CrossSpaceCompactionResource(
-              seqList.subList(1, seqList.size()), unseqList.subList(1, unseqList.size()));
-      // Although memory is out of memoryBudget, at least one unseq file should be selected
-      mergeFileSelector = new RewriteCompactionFileSelector(resource, 29000);
-      result = mergeFileSelector.select();
-      assertEquals(2, result.length);
+      long originMemoryBudget =
+          IoTDBDescriptor.getInstance().getConfig().getCrossCompactionMemoryBudget();
+      IoTDBDescriptor.getInstance().getConfig().setCrossCompactionMemoryBudget(29000);
+      try {
+        RewriteCrossSpaceCompactionSelector selector =
+            new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+        List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+            selector.selectCrossSpaceTask(seqList, unseqList);
+        assertEquals(1, selected.get(0).left.size());
+        assertEquals(1, selected.get(0).right.size());
+        assertEquals(seqList.get(0), selected.get(0).left.get(0));
+        assertEquals(unseqList.get(0), selected.get(0).right.get(0));
+
+        selected =
+            selector.selectCrossSpaceTask(
+                seqList.subList(1, seqList.size()), unseqList.subList(1, unseqList.size()));
+        assertEquals(1, selected.size());
+      } finally {
+        IoTDBDescriptor.getInstance()
+            .getConfig()
+            .setCrossCompactionMemoryBudget(originMemoryBudget);
+      }
 
     } finally {
       removeFiles(seqList, unseqList);
@@ -381,12 +386,19 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
     CrossSpaceCompactionResource resource = new CrossSpaceCompactionResource(seqList, unseqList);
     Assert.assertEquals(5, resource.getSeqFiles().size());
     Assert.assertEquals(10, resource.getUnseqFiles().size());
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, 500 * 1024 * 1024);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(1, result[0].size());
-    Assert.assertEquals(10, result[1].size());
+    long origin = IoTDBDescriptor.getInstance().getConfig().getCrossCompactionMemoryBudget();
+    IoTDBDescriptor.getInstance().getConfig().setCrossCompactionMemoryBudget(500 * 1024 * 1024);
+    try {
+      RewriteCrossSpaceCompactionSelector selector =
+          new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+      List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+          selector.selectCrossSpaceTask(seqList, unseqList);
+      Assert.assertEquals(1, selected.size());
+      Assert.assertEquals(1, selected.get(0).left.size());
+      Assert.assertEquals(10, selected.get(0).right.size());
+    } finally {
+      IoTDBDescriptor.getInstance().getConfig().setCrossCompactionMemoryBudget(origin);
+    }
   }
 
   /**
@@ -444,12 +456,19 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
     CrossSpaceCompactionResource resource = new CrossSpaceCompactionResource(seqList, unseqList);
     Assert.assertEquals(5, resource.getSeqFiles().size());
     Assert.assertEquals(1, resource.getUnseqFiles().size());
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, 500 * 1024 * 1024);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(1, result[0].size());
-    Assert.assertEquals(1, result[1].size());
+    long origin = IoTDBDescriptor.getInstance().getConfig().getCrossCompactionMemoryBudget();
+    IoTDBDescriptor.getInstance().getConfig().setCrossCompactionMemoryBudget(500 * 1024 * 1024);
+    try {
+      RewriteCrossSpaceCompactionSelector selector =
+          new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+      List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+          selector.selectCrossSpaceTask(seqList, unseqList);
+      Assert.assertEquals(1, selected.size());
+      Assert.assertEquals(1, selected.get(0).left.size());
+      Assert.assertEquals(1, selected.get(0).right.size());
+    } finally {
+      IoTDBDescriptor.getInstance().getConfig().setUdfMemoryBudgetInMB(origin);
+    }
   }
 
   /**
@@ -507,12 +526,19 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
     CrossSpaceCompactionResource resource = new CrossSpaceCompactionResource(seqList, unseqList);
     Assert.assertEquals(5, resource.getSeqFiles().size());
     Assert.assertEquals(2, resource.getUnseqFiles().size());
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, 500 * 1024 * 1024);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(3, result[0].size());
-    Assert.assertEquals(2, result[1].size());
+    long origin = IoTDBDescriptor.getInstance().getConfig().getCrossCompactionMemoryBudget();
+    IoTDBDescriptor.getInstance().getConfig().setCrossCompactionMemoryBudget(500 * 1024 * 1024);
+    try {
+      RewriteCrossSpaceCompactionSelector selector =
+          new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+      List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+          selector.selectCrossSpaceTask(seqList, unseqList);
+      Assert.assertEquals(1, selected.size());
+      Assert.assertEquals(3, selected.get(0).left.size());
+      Assert.assertEquals(2, selected.get(0).right.size());
+    } finally {
+      IoTDBDescriptor.getInstance().getConfig().setUdfMemoryBudgetInMB(origin);
+    }
   }
 
   /**
@@ -573,12 +599,19 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
     CrossSpaceCompactionResource resource = new CrossSpaceCompactionResource(seqList, unseqList);
     Assert.assertEquals(5, resource.getSeqFiles().size());
     Assert.assertEquals(4, resource.getUnseqFiles().size());
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, 500 * 1024 * 1024);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(5, result[0].size());
-    Assert.assertEquals(4, result[1].size());
+    long origin = IoTDBDescriptor.getInstance().getConfig().getCrossCompactionMemoryBudget();
+    IoTDBDescriptor.getInstance().getConfig().setCrossCompactionMemoryBudget(500 * 1024 * 1024);
+    try {
+      RewriteCrossSpaceCompactionSelector selector =
+          new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+      List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+          selector.selectCrossSpaceTask(seqList, unseqList);
+      Assert.assertEquals(1, selected.size());
+      Assert.assertEquals(5, selected.get(0).left.size());
+      Assert.assertEquals(4, selected.get(0).right.size());
+    } finally {
+      IoTDBDescriptor.getInstance().getConfig().setUdfMemoryBudgetInMB(origin);
+    }
   }
 
   /**
@@ -642,12 +675,19 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
     CrossSpaceCompactionResource resource = new CrossSpaceCompactionResource(seqList, unseqList);
     Assert.assertEquals(5, resource.getSeqFiles().size());
     Assert.assertEquals(4, resource.getUnseqFiles().size());
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, 500 * 1024 * 1024);
-    List[] result = mergeFileSelector.select();
-    Assert.assertEquals(2, result.length);
-    Assert.assertEquals(3, result[0].size());
-    Assert.assertEquals(2, result[1].size());
+    long origin = IoTDBDescriptor.getInstance().getConfig().getCrossCompactionMemoryBudget();
+    IoTDBDescriptor.getInstance().getConfig().setCrossCompactionMemoryBudget(500 * 1024 * 1024);
+    try {
+      RewriteCrossSpaceCompactionSelector selector =
+          new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+      List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+          selector.selectCrossSpaceTask(seqList, unseqList);
+      Assert.assertEquals(1, selected.size());
+      Assert.assertEquals(3, selected.get(0).left.size());
+      Assert.assertEquals(2, selected.get(0).right.size());
+    } finally {
+      IoTDBDescriptor.getInstance().getConfig().setUdfMemoryBudgetInMB(origin);
+    }
   }
 
   @Test
@@ -862,13 +902,19 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
     fileWriter.flushAllChunkGroups();
     fileWriter.close();
 
-    CrossSpaceCompactionResource compactionResource =
-        new CrossSpaceCompactionResource(seqList, unseqList);
-    RewriteCompactionFileSelector selector =
-        new RewriteCompactionFileSelector(compactionResource, 500 * 1024 * 1024);
-    List[] result = selector.select();
-    Assert.assertEquals(2, result[0].size());
-    Assert.assertEquals(2, result[1].size());
+    long origin = IoTDBDescriptor.getInstance().getConfig().getCrossCompactionMemoryBudget();
+    IoTDBDescriptor.getInstance().getConfig().setCrossCompactionMemoryBudget(500 * 1024 * 1024);
+    try {
+      RewriteCrossSpaceCompactionSelector selector =
+          new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+      List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+          selector.selectCrossSpaceTask(seqList, unseqList);
+      Assert.assertEquals(1, selected.size());
+      Assert.assertEquals(2, selected.get(0).left.size());
+      Assert.assertEquals(2, selected.get(0).right.size());
+    } finally {
+      IoTDBDescriptor.getInstance().getConfig().setUdfMemoryBudgetInMB(origin);
+    }
   }
 
   @Test
@@ -876,14 +922,13 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
     int oldMaxCrossCompactionCandidateFileNum =
         IoTDBDescriptor.getInstance().getConfig().getMaxCrossCompactionCandidateFileNum();
     IoTDBDescriptor.getInstance().getConfig().setMaxCrossCompactionCandidateFileNum(5);
-    CrossSpaceCompactionResource resource =
-        new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    assertEquals(2, result.length);
-    List<TsFileResource> seqSelected = result[0];
-    List<TsFileResource> unseqSelected = result[1];
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+    assertEquals(1, selected.size());
+    List<TsFileResource> seqSelected = selected.get(0).left;
+    List<TsFileResource> unseqSelected = selected.get(0).right;
     assertEquals(2, seqSelected.size());
     assertEquals(2, unseqSelected.size());
 
@@ -898,13 +943,13 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
         IoTDBDescriptor.getInstance().getConfig().getMaxCrossCompactionCandidateFileNum();
     IoTDBDescriptor.getInstance().getConfig().setMaxCrossCompactionCandidateFileNum(1);
 
-    CrossSpaceCompactionResource resource =
-        new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
-    List[] result = mergeFileSelector.select();
-    List<TsFileResource> seqSelected = result[0];
-    List<TsFileResource> unseqSelected = result[1];
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
+    List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+        selector.selectCrossSpaceTask(seqResources, unseqResources);
+    assertEquals(1, selected.size());
+    List<TsFileResource> seqSelected = selected.get(0).left;
+    List<TsFileResource> unseqSelected = selected.get(0).right;
     assertEquals(1, seqSelected.size());
     assertEquals(1, unseqSelected.size());
 
@@ -915,16 +960,15 @@ public class RewriteCompactionFileSelectorTest extends MergeTest {
 
   @Test
   public void testDeleteInSelection() throws Exception {
-    CrossSpaceCompactionResource resource =
-        new CrossSpaceCompactionResource(seqResources, unseqResources);
-    ICrossSpaceCompactionFileSelector mergeFileSelector =
-        new RewriteCompactionFileSelector(resource, Long.MAX_VALUE);
+    RewriteCrossSpaceCompactionSelector selector =
+        new RewriteCrossSpaceCompactionSelector("", "", 0, null);
     AtomicBoolean fail = new AtomicBoolean(false);
     Thread thread1 =
         new Thread(
             () -> {
               try {
-                mergeFileSelector.select();
+                List<Pair<List<TsFileResource>, List<TsFileResource>>> selected =
+                    selector.selectCrossSpaceTask(seqResources, unseqResources);
               } catch (Exception e) {
                 logger.error("Exception occurs", e);
                 fail.set(true);