You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by qi...@apache.org on 2020/02/23 10:07:28 UTC

[incubator-iotdb] branch master updated: [IOTDB-274] Refactor MManager (#793)

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

qiaojialin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 1969b54  [IOTDB-274] Refactor MManager (#793)
1969b54 is described below

commit 1969b54dad5a804d2f0af021e913eddb96705192
Author: Zesong Sun <sz...@mails.tsinghua.edu.cn>
AuthorDate: Sun Feb 23 18:07:19 2020 +0800

    [IOTDB-274] Refactor MManager (#793)
    
    * Refactor MManager
    Co-authored-by: Jialin Qiao <qj...@mails.tsinghua.edu.cn>
---
 .../org/apache/iotdb/hive/TsFileTestHelper.java    |   11 +-
 .../resources/conf/iotdb-engine.properties         |   19 +-
 .../org/apache/iotdb/db/auth/AuthorityChecker.java |    1 -
 .../org/apache/iotdb/db/conf/IoTDBConstant.java    |    2 +
 .../org/apache/iotdb/db/conf/IoTDBDescriptor.java  |    5 +-
 .../org/apache/iotdb/db/engine/StorageEngine.java  |   68 +-
 .../iotdb/db/engine/merge/recover/LogAnalyzer.java |    2 +-
 .../iotdb/db/engine/merge/task/MergeTask.java      |    4 +-
 .../engine/storagegroup/StorageGroupProcessor.java |    8 +-
 .../apache/iotdb/db/exception/IoTDBException.java  |    7 +-
 .../IllegalPathException.java}                     |   10 +-
 .../db/exception/metadata/MetadataException.java   |    5 +
 ...ception.java => PathAlreadyExistException.java} |    9 +-
 .../PathNotExistException.java}                    |   13 +-
 .../StorageGroupAlreadySetException.java}          |   13 +-
 .../StorageGroupNotSetException.java               |    4 +-
 .../db/exception/path/MTreePathException.java      |   37 -
 .../exception/{path => query}/PathException.java   |    3 +-
 .../storageGroup/StorageGroupPathException.java    |   30 -
 .../java/org/apache/iotdb/db/metadata/MGraph.java  |  419 ------
 .../org/apache/iotdb/db/metadata/MManager.java     | 1345 ++++++--------------
 .../java/org/apache/iotdb/db/metadata/MNode.java   |  241 ----
 .../java/org/apache/iotdb/db/metadata/MTree.java   | 1095 +++++-----------
 .../org/apache/iotdb/db/metadata/MetaUtils.java    |   60 +-
 .../iotdb/db/metadata/MetadataOperationType.java   |   15 +-
 .../java/org/apache/iotdb/db/metadata/PNode.java   |  127 --
 .../java/org/apache/iotdb/db/metadata/PTree.java   |  244 ----
 .../iotdb/db/metadata/mnode/InternalMNode.java     |   74 ++
 .../apache/iotdb/db/metadata/mnode/LeafMNode.java  |   77 ++
 .../org/apache/iotdb/db/metadata/mnode/MNode.java  |  116 ++
 .../iotdb/db/metadata/mnode/StorageGroupMNode.java |   59 +
 .../org/apache/iotdb/db/monitor/StatMonitor.java   |   21 +-
 .../iotdb/db/monitor/collector/FileSize.java       |    9 +-
 .../main/java/org/apache/iotdb/db/qp/Planner.java  |    1 -
 .../apache/iotdb/db/qp/executor/PlanExecutor.java  |  376 +++---
 .../org/apache/iotdb/db/qp/logical/Operator.java   |    2 +-
 .../db/qp/logical/crud/BasicFunctionOperator.java  |    8 +-
 .../iotdb/db/qp/logical/crud/FilterOperator.java   |   26 +-
 .../iotdb/db/qp/logical/crud/InOperator.java       |    8 +-
 .../iotdb/db/qp/logical/sys/PropertyOperator.java  |  106 --
 .../iotdb/db/qp/physical/sys/PropertyPlan.java     |   95 --
 .../iotdb/db/qp/strategy/LogicalGenerator.java     |   74 +-
 .../iotdb/db/qp/strategy/PhysicalGenerator.java    |   21 +-
 .../qp/strategy/optimizer/ConcatPathOptimizer.java |    4 +-
 .../groupby/GroupByWithValueFilterDataSet.java     |    2 +-
 .../db/query/executor/AggregationExecutor.java     |    2 +-
 .../iotdb/db/query/factory/AggreResultFactory.java |    2 +-
 .../query/timegenerator/ServerTimeGenerator.java   |    1 -
 .../org/apache/iotdb/db/service/TSServiceImpl.java |   19 +-
 .../db/sync/receiver/transfer/SyncServiceImpl.java |    5 +-
 .../db/sync/sender/manage/SyncFileManager.java     |   12 +-
 .../apache/iotdb/db/utils/RandomDeleteCache.java   |   16 +-
 .../org/apache/iotdb/db/utils/SchemaUtils.java     |   17 +-
 .../iotdb/db/engine/MetadataManagerHelper.java     |   85 +-
 .../db/engine/cache/DeviceMetaDataCacheTest.java   |   13 +-
 .../apache/iotdb/db/engine/merge/MergeLogTest.java |    2 +-
 .../iotdb/db/engine/merge/MergeOverLapTest.java    |    2 +-
 .../iotdb/db/engine/merge/MergeTaskTest.java       |    2 +-
 .../apache/iotdb/db/engine/merge/MergeTest.java    |    6 +-
 .../engine/modification/DeletionFileNodeTest.java  |   11 +-
 .../db/engine/modification/DeletionQueryTest.java  |    8 +-
 .../storagegroup/FileNodeManagerBenchmark.java     |    6 +-
 .../storagegroup/StorageGroupProcessorTest.java    |    4 +-
 .../iotdb/db/engine/storagegroup/TTLTest.java      |   48 +-
 .../engine/storagegroup/TsFileProcessorTest.java   |   10 +-
 .../iotdb/db/integration/IoTDBAuthorizationIT.java |    2 +-
 .../db/integration/IoTDBFlushQueryMergeTest.java   |   19 +-
 .../integration/IoTDBLoadExternalTsfileTest.java   |   36 +-
 .../iotdb/db/integration/IoTDBMetadataFetchIT.java |   10 +-
 .../iotdb/db/integration/IoTDBMultiSeriesIT.java   |    2 +-
 .../apache/iotdb/db/integration/IoTDBTtlIT.java    |   22 +-
 .../org/apache/iotdb/db/metadata/MGraphTest.java   |   81 --
 .../iotdb/db/metadata/MManagerAdvancedTest.java    |   85 +-
 .../iotdb/db/metadata/MManagerBasicTest.java       |  299 ++---
 .../iotdb/db/metadata/MManagerImproveTest.java     |  137 +-
 .../org/apache/iotdb/db/metadata/MTreeTest.java    |  295 ++---
 .../org/apache/iotdb/db/metadata/MetadataTest.java |   88 --
 .../java/org/apache/iotdb/db/qp/PlannerTest.java   |   36 +-
 .../db/qp/other/TSPlanContextPropertyTest.java     |   89 --
 ...ncatOptimizer.java => ConcatOptimizerTest.java} |   22 +-
 .../apache/iotdb/db/qp/plan/PhysicalPlanTest.java  |   30 +-
 .../query/executor/GroupByEngineDataSetTest.java   |    2 +-
 .../reader/series/SeriesAggregateReaderTest.java   |    2 +-
 .../reader/series/SeriesReaderByTimestampTest.java |    2 +-
 .../db/query/reader/series/SeriesReaderTest.java   |    2 +-
 .../query/reader/series/SeriesReaderTestUtil.java  |    6 +-
 .../db/sync/receiver/load/FileLoaderTest.java      |    6 +-
 .../recover/SyncReceiverLogAnalyzerTest.java       |    6 +-
 .../db/sync/sender/manage/SyncFileManagerTest.java |    2 +-
 .../sender/recover/SyncSenderLogAnalyzerTest.java  |    2 +-
 .../apache/iotdb/db/writelog/PerformanceTest.java  |   15 +-
 .../java/org/apache/iotdb/rpc/TSStatusCode.java    |    8 +-
 .../org/apache/iotdb/session/IoTDBSessionIT.java   |    2 +-
 .../iotdb/tsfile/common/conf/TSFileConfig.java     |    7 +-
 .../iotdb/tsfile/common/conf/TSFileDescriptor.java |    2 +-
 .../tsfile/common/constant/TsFileConstant.java     |    1 -
 .../iotdb/tsfile/read/TsFileSequenceReader.java    |   17 +-
 .../tsfile/write/schema/MeasurementSchema.java     |    2 +-
 .../org/apache/iotdb/tsfile/write/WriteTest.java   |   12 +-
 99 files changed, 1922 insertions(+), 4574 deletions(-)

diff --git a/hive-connector/src/test/java/org/apache/iotdb/hive/TsFileTestHelper.java b/hive-connector/src/test/java/org/apache/iotdb/hive/TsFileTestHelper.java
index f9472ed..ac43ee5 100644
--- a/hive-connector/src/test/java/org/apache/iotdb/hive/TsFileTestHelper.java
+++ b/hive-connector/src/test/java/org/apache/iotdb/hive/TsFileTestHelper.java
@@ -18,6 +18,10 @@
  */
 package org.apache.iotdb.hive;
 
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
@@ -28,10 +32,6 @@ import org.apache.iotdb.tsfile.write.schema.Schema;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
 public class TsFileTestHelper {
 
 
@@ -61,7 +61,8 @@ public class TsFileTestHelper {
       // add measurements into file schema (all with INT64 data type)
       for (int i = 0; i < sensorNum; i++) {
         schema.registerMeasurement(
-                new MeasurementSchema("sensor_" + (i + 1), TSDataType.INT64, TSEncoding.TS_2DIFF));
+            new MeasurementSchema("sensor_" + (i + 1), TSDataType.INT64, TSEncoding.TS_2DIFF,
+                CompressionType.UNCOMPRESSED));
       }
 
       // add measurements into TSFileWriter
diff --git a/server/src/assembly/resources/conf/iotdb-engine.properties b/server/src/assembly/resources/conf/iotdb-engine.properties
index 7ea2daf..f9906c7 100644
--- a/server/src/assembly/resources/conf/iotdb-engine.properties
+++ b/server/src/assembly/resources/conf/iotdb-engine.properties
@@ -282,6 +282,9 @@ meta_data_cache_enable=true
 # The parameter form is a:b:c:d, where a, b, c and d are integers. for example: 1:1:1:1 , 3:6:10:20
 filemeta_chunkmeta_chunk_free_memory_proportion=3:6:10:20
 
+# cache size for MManager.
+# This cache is used to improve insert speed where all path check and TSDataType will be cached in MManager with corresponding Path.
+metadata_node_cache_size=300000
 
 ####################
 ### Statistics Monitor configuration
@@ -306,10 +309,6 @@ stat_monitor_detect_freq_in_second=600
 # The time unit is seconds.
 stat_monitor_retain_interval_in_second=600
 
-# cache size for MManager.
-# This cache is used to improve insert speed where all path check and TSDataType will be cached in MManager with corresponding Path.
-schema_manager_cache_size=300000
-
 ####################
 ### External sort Configuration
 ####################
@@ -404,7 +403,7 @@ page_size_in_byte=65536
 max_number_of_points_in_page=1048576
 
 # Data type configuration
-# Data type for input timestamp, TsFile supports INT32 or INT64
+# Data type for input timestamp, supports INT32 or INT64
 time_series_data_type=INT64
 
 # Max size limitation of input string
@@ -414,17 +413,17 @@ max_string_length=128
 float_precision=2
 
 # Encoder configuration
-# Encoder of time series, TsFile supports TS_2DIFF, PLAIN and RLE(run-length encoding) and default value is TS_2DIFF
+# Encoder of time series, supports TS_2DIFF, PLAIN and RLE(run-length encoding) and default value is TS_2DIFF
 time_encoder=TS_2DIFF
 
 # Encoder of value series. default value is PLAIN.
-# For int, long data type, TsFile also supports TS_2DIFF and RLE(run-length encoding).
-# For float, double data type, TsFile also supports TS_2DIFF, RLE(run-length encoding) and GORILLA.
-# For text data type, TsFile only supports PLAIN.
+# For int, long data type, also supports TS_2DIFF and RLE(run-length encoding).
+# For float, double data type, also supports TS_2DIFF, RLE(run-length encoding) and GORILLA.
+# For text data type, only supports PLAIN.
 value_encoder=PLAIN
 
 # Compression configuration
-# Data compression method, TsFile supports UNCOMPRESSED or SNAPPY. Default value is UNCOMPRESSED which means no compression
+# Data compression method, supports UNCOMPRESSED or SNAPPY. Default value is SNAPPY
 compressor=SNAPPY
 
 # Time range for divide storage group
diff --git a/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java b/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
index 68cb93b..990e7a1 100644
--- a/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
+++ b/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
@@ -156,7 +156,6 @@ public class AuthorityChecker {
       case MERGEJOIN:
       case NULL:
       case ORDERBY:
-      case PROPERTY:
       case SFW:
       case UNION:
         logger.error("Illegal operator type authorization : {}", type);
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
index b7514f5..18b74a3 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConstant.java
@@ -75,6 +75,8 @@ public class IoTDBConstant {
   public static final String COLUMN_STORAGE_GROUP = "storage group";
   public static final String COLUMN_TTL = "ttl";
 
+  public static final String PATH_WILDCARD = "*";
+
   // data folder name
   public static final String SEQUENCE_FLODER_NAME = "sequence";
   public static final String UNSEQUENCE_FLODER_NAME = "unsequence";
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
index 620ea79..7eea742 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
@@ -213,7 +213,7 @@ public class IoTDBDescriptor {
       }
 
       conf.setmManagerCacheSize(Integer
-          .parseInt(properties.getProperty("schema_manager_cache_size",
+          .parseInt(properties.getProperty("metadata_node_cache_size",
               Integer.toString(conf.getmManagerCacheSize())).trim()));
 
       conf.setLanguageVersion(properties.getProperty("language_version",
@@ -452,7 +452,8 @@ public class IoTDBDescriptor {
         .getProperty("value_encoder",
             TSFileDescriptor.getInstance().getConfig().getValueEncoder()));
     TSFileDescriptor.getInstance().getConfig().setCompressor(properties
-        .getProperty("compressor", TSFileDescriptor.getInstance().getConfig().getCompressor()));
+        .getProperty("compressor",
+            TSFileDescriptor.getInstance().getConfig().getCompressor().toString()));
   }
 
   public void loadHotModifiedProps() throws QueryProcessException {
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/StorageEngine.java b/server/src/main/java/org/apache/iotdb/db/engine/StorageEngine.java
index 216de5c..cf99279 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/StorageEngine.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/StorageEngine.java
@@ -18,6 +18,22 @@
  */
 package org.apache.iotdb.db.engine;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.ConcurrentModificationException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 import org.apache.commons.io.FileUtils;
 import org.apache.iotdb.db.concurrent.IoTDBThreadPoolFactory;
 import org.apache.iotdb.db.conf.IoTDBConfig;
@@ -31,14 +47,13 @@ import org.apache.iotdb.db.engine.storagegroup.TsFileProcessor;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.TsFileProcessorException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
+import org.apache.iotdb.db.exception.metadata.StorageGroupNotSetException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.exception.runtime.StorageEngineFailureException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupNotSetException;
 import org.apache.iotdb.db.exception.storageGroup.StorageGroupProcessorException;
 import org.apache.iotdb.db.metadata.MManager;
-import org.apache.iotdb.db.metadata.MNode;
+import org.apache.iotdb.db.metadata.mnode.StorageGroupMNode;
 import org.apache.iotdb.db.qp.physical.crud.BatchInsertPlan;
 import org.apache.iotdb.db.qp.physical.crud.InsertPlan;
 import org.apache.iotdb.db.query.context.QueryContext;
@@ -47,6 +62,7 @@ import org.apache.iotdb.db.service.IService;
 import org.apache.iotdb.db.service.ServiceType;
 import org.apache.iotdb.db.utils.FilePathUtils;
 import org.apache.iotdb.db.utils.UpgradeUtils;
+import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
@@ -55,11 +71,6 @@ import org.apache.iotdb.tsfile.read.expression.impl.SingleSeriesExpression;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.*;
-
 public class StorageEngine implements IService {
 
   private final Logger logger;
@@ -105,9 +116,9 @@ public class StorageEngine implements IService {
      * recover all storage group processors.
      */
 
-    List<MNode> sgNodes = MManager.getInstance().getAllStorageGroups();
+    List<StorageGroupMNode> sgNodes = MManager.getInstance().getAllStorageGroupNodes();
     List<Future> futures = new ArrayList<>();
-    for (MNode storageGroup : sgNodes) {
+    for (StorageGroupMNode storageGroup : sgNodes) {
       futures.add(recoveryThreadPool.submit((Callable<Void>) () -> {
         StorageGroupProcessor processor = new StorageGroupProcessor(systemDir,
             storageGroup.getFullPath(), fileFlushPolicy);
@@ -167,7 +178,7 @@ public class StorageEngine implements IService {
   public StorageGroupProcessor getProcessor(String path) throws StorageEngineException {
     String storageGroupName = "";
     try {
-      storageGroupName = MManager.getInstance().getStorageGroupNameByPath(path);
+      storageGroupName = MManager.getInstance().getStorageGroupName(path);
       StorageGroupProcessor processor;
       processor = processorMap.get(storageGroupName);
       if (processor == null) {
@@ -178,15 +189,15 @@ public class StorageEngine implements IService {
             logger.info("construct a processor instance, the storage group is {}, Thread is {}",
                 storageGroupName, Thread.currentThread().getId());
             processor = new StorageGroupProcessor(systemDir, storageGroupName, fileFlushPolicy);
-            processor.setDataTTL(
-                MManager.getInstance().getNodeByPathWithCheck(storageGroupName).getDataTTL());
+            StorageGroupMNode storageGroup = MManager.getInstance()
+                .getStorageGroupNode(storageGroupName);
+            processor.setDataTTL(storageGroup.getDataTTL());
             processorMap.put(storageGroupName, processor);
           }
         }
       }
       return processor;
-    } catch (StorageGroupException | StorageGroupProcessorException | PathException e) {
-      logger.error("Fail to get StorageGroupProcessor {}", storageGroupName, e);
+    } catch (StorageGroupProcessorException | MetadataException e) {
       throw new StorageEngineException(e);
     }
   }
@@ -269,15 +280,16 @@ public class StorageEngine implements IService {
           isSeq);
       processor.writeLock();
       try {
-        if(isSeq) {
+        if (isSeq) {
           // to avoid concurrent modification problem, we need a new array list
-          for (TsFileProcessor tsfileProcessor : new ArrayList<>(processor.getWorkSequenceTsFileProcessors())) {
+          for (TsFileProcessor tsfileProcessor : new ArrayList<>(
+              processor.getWorkSequenceTsFileProcessors())) {
             processor.moveOneWorkProcessorToClosingList(true, tsfileProcessor);
           }
-        }
-        else {
+        } else {
           // to avoid concurrent modification problem, we need a new array list
-          for (TsFileProcessor tsfileProcessor : new ArrayList<>(processor.getWorkUnsequenceTsFileProcessor())) {
+          for (TsFileProcessor tsfileProcessor : new ArrayList<>(
+              processor.getWorkUnsequenceTsFileProcessor())) {
             processor.moveOneWorkProcessorToClosingList(false, tsfileProcessor);
           }
         }
@@ -400,6 +412,16 @@ public class StorageEngine implements IService {
         .addMeasurement(path.getMeasurement(), dataType, encoding, compressor, props);
   }
 
+  public void addTimeSeries(Path path, TSDataType dataType, TSEncoding encoding)
+      throws StorageEngineException {
+    StorageGroupProcessor storageGroupProcessor = getProcessor(path.getDevice());
+    CompressionType compressor =
+        TSFileDescriptor.getInstance().getConfig().getCompressor();
+    storageGroupProcessor
+        .addMeasurement(path.getMeasurement(), dataType, encoding, compressor,
+            Collections.emptyMap());
+  }
+
 
   /**
    * delete all data of storage groups' timeseries.
@@ -433,13 +455,13 @@ public class StorageEngine implements IService {
   }
 
   public void loadNewTsFile(TsFileResource newTsFileResource)
-      throws TsFileProcessorException, StorageEngineException, StorageGroupException {
+      throws TsFileProcessorException, StorageEngineException, MetadataException {
     Map<String, Long> startTimeMap = newTsFileResource.getStartTimeMap();
     if (startTimeMap == null || startTimeMap.isEmpty()) {
       throw new StorageEngineException("Can not get the corresponding storage group.");
     }
     String device = startTimeMap.keySet().iterator().next();
-    String storageGroupName = MManager.getInstance().getStorageGroupNameByPath(device);
+    String storageGroupName = MManager.getInstance().getStorageGroupName(device);
     getProcessor(storageGroupName).loadNewTsFile(newTsFileResource);
   }
 
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/merge/recover/LogAnalyzer.java b/server/src/main/java/org/apache/iotdb/db/engine/merge/recover/LogAnalyzer.java
index b156e3c..7d9fc9e 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/merge/recover/LogAnalyzer.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/merge/recover/LogAnalyzer.java
@@ -99,7 +99,7 @@ public class LogAnalyzer {
 
         analyzeUnseqFiles(bufferedReader);
 
-        List<String> storageGroupPaths = MManager.getInstance().getPaths(storageGroupName + ".*");
+        List<String> storageGroupPaths = MManager.getInstance().getAllTimeseriesName(storageGroupName + ".*");
         unmergedPaths = new ArrayList<>();
         for (String path : storageGroupPaths) {
           unmergedPaths.add(new Path(path));
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/merge/task/MergeTask.java b/server/src/main/java/org/apache/iotdb/db/engine/merge/task/MergeTask.java
index 35eabd0..533bd9f 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/merge/task/MergeTask.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/merge/task/MergeTask.java
@@ -111,10 +111,10 @@ public class MergeTask implements Callable<Void> {
     mergeLogger.logFiles(resource);
 
     List<MeasurementSchema> measurementSchemas = MManager.getInstance()
-        .getSchemaForStorageGroup(storageGroupName);
+        .getStorageGroupSchema(storageGroupName);
     resource.addMeasurements(measurementSchemas);
 
-    List<String> storageGroupPaths = MManager.getInstance().getPaths(storageGroupName + ".*");
+    List<String> storageGroupPaths = MManager.getInstance().getAllTimeseriesName(storageGroupName + ".*");
     List<Path> unmergedSeries = new ArrayList<>();
     for (String path : storageGroupPaths) {
       unmergedSeries.add(new Path(path));
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessor.java b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessor.java
index 2ec8676..547b9c8 100755
--- a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessor.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessor.java
@@ -205,7 +205,7 @@ public class StorageGroupProcessor {
 
   public StorageGroupProcessor(String systemInfoDir, String storageGroupName,
       TsFileFlushPolicy fileFlushPolicy)
-      throws StorageGroupProcessorException {
+      throws StorageGroupProcessorException, MetadataException {
     this.storageGroupName = storageGroupName;
     this.fileFlushPolicy = fileFlushPolicy;
 
@@ -445,9 +445,9 @@ public class StorageGroupProcessor {
     }
   }
 
-  private Schema constructSchema(String storageGroupName) {
-    List<MeasurementSchema> columnSchemaList;
-    columnSchemaList = MManager.getInstance().getSchemaForStorageGroup(storageGroupName);
+  private Schema constructSchema(String storageGroupName) throws MetadataException {
+    List<MeasurementSchema> columnSchemaList =
+        MManager.getInstance().getStorageGroupSchema(storageGroupName);
 
     Schema newSchema = new Schema();
     for (MeasurementSchema measurementSchema : columnSchemaList) {
diff --git a/server/src/main/java/org/apache/iotdb/db/exception/IoTDBException.java b/server/src/main/java/org/apache/iotdb/db/exception/IoTDBException.java
index 2e08778..90c16a0 100644
--- a/server/src/main/java/org/apache/iotdb/db/exception/IoTDBException.java
+++ b/server/src/main/java/org/apache/iotdb/db/exception/IoTDBException.java
@@ -23,13 +23,18 @@ package org.apache.iotdb.db.exception;
 public class IoTDBException extends Exception {
 
   private static final long serialVersionUID = 8480450962311247736L;
-  protected final int errorCode;
+  protected int errorCode;
 
   public IoTDBException(String message, int errorCode) {
     super(message);
     this.errorCode = errorCode;
   }
 
+  public IoTDBException(Throwable cause, int errorCode) {
+    super(cause);
+    this.errorCode = errorCode;
+  }
+
   public int getErrorCode() {
     return errorCode;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/exception/path/NotStorageGroupException.java b/server/src/main/java/org/apache/iotdb/db/exception/metadata/IllegalPathException.java
similarity index 76%
rename from server/src/main/java/org/apache/iotdb/db/exception/path/NotStorageGroupException.java
rename to server/src/main/java/org/apache/iotdb/db/exception/metadata/IllegalPathException.java
index 09f5685..8f9ee27 100644
--- a/server/src/main/java/org/apache/iotdb/db/exception/path/NotStorageGroupException.java
+++ b/server/src/main/java/org/apache/iotdb/db/exception/metadata/IllegalPathException.java
@@ -18,16 +18,16 @@
  *
  */
 
-package org.apache.iotdb.db.exception.path;
+package org.apache.iotdb.db.exception.metadata;
 
 import org.apache.iotdb.rpc.TSStatusCode;
 
-public class NotStorageGroupException extends PathException {
+public class IllegalPathException extends MetadataException {
 
   private static final long serialVersionUID = 2693272249167539978L;
 
-  public NotStorageGroupException(String path) {
-    super(String.format("[%s] is not a storage group", path),
-        TSStatusCode.NOT_STORAGE_GROUP_ERROR.getStatusCode());
+  public IllegalPathException(String path) {
+    super(String.format("%s is not a legal path", path));
+    errorCode = TSStatusCode.PATH_ILLEGAL.getStatusCode();
   }
 }
\ No newline at end of file
diff --git a/server/src/main/java/org/apache/iotdb/db/exception/metadata/MetadataException.java b/server/src/main/java/org/apache/iotdb/db/exception/metadata/MetadataException.java
index 004df41..dfca520 100644
--- a/server/src/main/java/org/apache/iotdb/db/exception/metadata/MetadataException.java
+++ b/server/src/main/java/org/apache/iotdb/db/exception/metadata/MetadataException.java
@@ -29,6 +29,11 @@ public class MetadataException extends IoTDBException {
 
   private static final long serialVersionUID = 3415275599091623570L;
 
+  public MetadataException(Throwable cause, int errorCode) {
+    super(cause, TSStatusCode.METADATA_ERROR.getStatusCode());
+    this.errorCode = errorCode;
+  }
+
   public MetadataException(String msg) {
     super(msg, TSStatusCode.METADATA_ERROR.getStatusCode());
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/exception/metadata/TimeseriesAlreadyExistException.java b/server/src/main/java/org/apache/iotdb/db/exception/metadata/PathAlreadyExistException.java
similarity index 78%
rename from server/src/main/java/org/apache/iotdb/db/exception/metadata/TimeseriesAlreadyExistException.java
rename to server/src/main/java/org/apache/iotdb/db/exception/metadata/PathAlreadyExistException.java
index e719e3d..5b2406f 100644
--- a/server/src/main/java/org/apache/iotdb/db/exception/metadata/TimeseriesAlreadyExistException.java
+++ b/server/src/main/java/org/apache/iotdb/db/exception/metadata/PathAlreadyExistException.java
@@ -22,13 +22,12 @@ package org.apache.iotdb.db.exception.metadata;
 
 import org.apache.iotdb.rpc.TSStatusCode;
 
-public class TimeseriesAlreadyExistException extends MetadataException {
-
+public class PathAlreadyExistException extends MetadataException {
 
   private static final long serialVersionUID = -6713847897890531438L;
 
-  public TimeseriesAlreadyExistException(String path) {
-    super(String.format("Timeseries [%s] already exist", path),
-        TSStatusCode.TIMESERIES_ALREADY_EXIST_ERROR.getStatusCode());
+  public PathAlreadyExistException(String path) {
+    super(String.format("Path [%s] already exist", path),
+        TSStatusCode.PATH_ALREADY_EXIST_ERROR.getStatusCode());
   }
 }
\ No newline at end of file
diff --git a/server/src/main/java/org/apache/iotdb/db/exception/path/PTreePathException.java b/server/src/main/java/org/apache/iotdb/db/exception/metadata/PathNotExistException.java
similarity index 73%
rename from server/src/main/java/org/apache/iotdb/db/exception/path/PTreePathException.java
rename to server/src/main/java/org/apache/iotdb/db/exception/metadata/PathNotExistException.java
index f5d8905..fe8e476 100644
--- a/server/src/main/java/org/apache/iotdb/db/exception/path/PTreePathException.java
+++ b/server/src/main/java/org/apache/iotdb/db/exception/metadata/PathNotExistException.java
@@ -15,13 +15,16 @@
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
+ *
  */
 
-package org.apache.iotdb.db.exception.path;
+package org.apache.iotdb.db.exception.metadata;
+
+public class PathNotExistException extends MetadataException {
 
-public class PTreePathException extends PathException {
+  private static final long serialVersionUID = 2693272249167539978L;
 
-  public PTreePathException(String message) {
-    super(message);
+  public PathNotExistException(String path) {
+    super(String.format("Path [%s] does not exist", path));
   }
-}
+}
\ No newline at end of file
diff --git a/server/src/main/java/org/apache/iotdb/db/exception/storageGroup/StorageGroupNotSetException.java b/server/src/main/java/org/apache/iotdb/db/exception/metadata/StorageGroupAlreadySetException.java
similarity index 71%
copy from server/src/main/java/org/apache/iotdb/db/exception/storageGroup/StorageGroupNotSetException.java
copy to server/src/main/java/org/apache/iotdb/db/exception/metadata/StorageGroupAlreadySetException.java
index b6137a8..c43884a 100644
--- a/server/src/main/java/org/apache/iotdb/db/exception/storageGroup/StorageGroupNotSetException.java
+++ b/server/src/main/java/org/apache/iotdb/db/exception/metadata/StorageGroupAlreadySetException.java
@@ -15,15 +15,16 @@
  * KIND, either express or implied.  See the License for the
  * specific language governing permissions and limitations
  * under the License.
+ *
  */
 
-package org.apache.iotdb.db.exception.storageGroup;
+package org.apache.iotdb.db.exception.metadata;
 
-public class StorageGroupNotSetException extends StorageGroupException {
+public class StorageGroupAlreadySetException extends MetadataException {
 
-  private static final long serialVersionUID = 3739300272099030533L;
+  private static final long serialVersionUID = 9110669164701929779L;
 
-  public StorageGroupNotSetException(String path) {
-    super(String.format("Storage group is not set for current seriesPath: [%s]", path));
+  public StorageGroupAlreadySetException(String path) {
+    super(String.format("%s has already been set to storage group", path));
   }
-}
+}
\ No newline at end of file
diff --git a/server/src/main/java/org/apache/iotdb/db/exception/storageGroup/StorageGroupNotSetException.java b/server/src/main/java/org/apache/iotdb/db/exception/metadata/StorageGroupNotSetException.java
similarity index 89%
rename from server/src/main/java/org/apache/iotdb/db/exception/storageGroup/StorageGroupNotSetException.java
rename to server/src/main/java/org/apache/iotdb/db/exception/metadata/StorageGroupNotSetException.java
index b6137a8..62d6a5f 100644
--- a/server/src/main/java/org/apache/iotdb/db/exception/storageGroup/StorageGroupNotSetException.java
+++ b/server/src/main/java/org/apache/iotdb/db/exception/metadata/StorageGroupNotSetException.java
@@ -17,9 +17,9 @@
  * under the License.
  */
 
-package org.apache.iotdb.db.exception.storageGroup;
+package org.apache.iotdb.db.exception.metadata;
 
-public class StorageGroupNotSetException extends StorageGroupException {
+public class StorageGroupNotSetException extends MetadataException {
 
   private static final long serialVersionUID = 3739300272099030533L;
 
diff --git a/server/src/main/java/org/apache/iotdb/db/exception/path/MTreePathException.java b/server/src/main/java/org/apache/iotdb/db/exception/path/MTreePathException.java
deleted file mode 100644
index 397d9b5..0000000
--- a/server/src/main/java/org/apache/iotdb/db/exception/path/MTreePathException.java
+++ /dev/null
@@ -1,37 +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.exception.path;
-
-public class MTreePathException extends PathException {
-
-  private static final long serialVersionUID = 5633901351119088504L;
-
-  public MTreePathException(String error, String path) {
-    super(String.format("%s [%s] is not correct. ", error, path));
-  }
-
-  public MTreePathException(String timeseriesPath, String error, String message) {
-    super(String.format("Timeseries [%s] %s. %s", timeseriesPath, error, message));
-  }
-
-  public MTreePathException(String message) {
-    super(message);
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/exception/path/PathException.java b/server/src/main/java/org/apache/iotdb/db/exception/query/PathException.java
similarity index 92%
rename from server/src/main/java/org/apache/iotdb/db/exception/path/PathException.java
rename to server/src/main/java/org/apache/iotdb/db/exception/query/PathException.java
index 8049cb1..5fd792b 100644
--- a/server/src/main/java/org/apache/iotdb/db/exception/path/PathException.java
+++ b/server/src/main/java/org/apache/iotdb/db/exception/query/PathException.java
@@ -16,9 +16,8 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.iotdb.db.exception.path;
+package org.apache.iotdb.db.exception.query;
 
-import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 public class PathException extends QueryProcessException {
diff --git a/server/src/main/java/org/apache/iotdb/db/exception/storageGroup/StorageGroupPathException.java b/server/src/main/java/org/apache/iotdb/db/exception/storageGroup/StorageGroupPathException.java
deleted file mode 100644
index 907e9c6..0000000
--- a/server/src/main/java/org/apache/iotdb/db/exception/storageGroup/StorageGroupPathException.java
+++ /dev/null
@@ -1,30 +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.exception.storageGroup;
-
-public class StorageGroupPathException extends StorageGroupException {
-
-  private static final long serialVersionUID = 3739300272099030533L;
-
-  public StorageGroupPathException(String path) {
-    super(String
-        .format("The prefix of the seriesPath [%s] is not one storage group seriesPath", path));
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MGraph.java b/server/src/main/java/org/apache/iotdb/db/metadata/MGraph.java
deleted file mode 100644
index 299e28c..0000000
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MGraph.java
+++ /dev/null
@@ -1,419 +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.metadata;
-
-import java.io.Serializable;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.MTreePathException;
-import org.apache.iotdb.db.exception.path.PathException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
-import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
-import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
-import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
-import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
-
-/**
- * Metadata Graph consists of one {@code MTree} and several {@code PTree}.
- */
-public class MGraph implements Serializable {
-
-  private static final long serialVersionUID = 8214849219614352834L;
-  private static final String DOUB_SEPARATOR = "\\.";
-  private MTree mtree;
-  private HashMap<String, PTree> ptreeMap;
-
-  MGraph(String mtreeName) {
-    mtree = new MTree(mtreeName);
-    ptreeMap = new HashMap<>();
-  }
-
-  /**
-   * Add a {@code PTree} to current {@code MGraph}.
-   */
-  void addAPTree(String ptreeRootName) throws MetadataException {
-    if (MetadataConstant.ROOT.equalsIgnoreCase(ptreeRootName)) {
-      throw new MetadataException("Property Tree's root name should not be 'root'");
-    }
-    PTree ptree = new PTree(ptreeRootName, mtree);
-    ptreeMap.put(ptreeRootName, ptree);
-  }
-
-  /**
-   * this is just for compatibility
-   */
-  public void addPathToMTree(String path, String dataType, String encoding)
-      throws PathException {
-    TSDataType tsDataType = TSDataType.valueOf(dataType);
-    TSEncoding tsEncoding = TSEncoding.valueOf(encoding);
-    CompressionType compressionType = CompressionType
-        .valueOf(TSFileDescriptor.getInstance().getConfig().getCompressor());
-    addPathToMTree(path, tsDataType, tsEncoding, compressionType,
-        Collections.emptyMap());
-  }
-
-  /**
-   * Add a seriesPath to Metadata Tree.
-   *
-   * @param path Format: root.node.(node)*
-   */
-  public void addPathToMTree(String path, TSDataType dataType, TSEncoding encoding,
-      CompressionType compressor, Map<String, String> props) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, DOUB_SEPARATOR);
-    if (nodes.length == 0) {
-      throw new PathException();
-    }
-    mtree.addTimeseriesPath(path, dataType, encoding, compressor, props);
-  }
-
-  /**
-   * Add a deviceId to Metadata Tree.
-   */
-  MNode addDeviceIdToMTree(String deviceId) throws PathException {
-    return mtree.addDeviceId(deviceId);
-  }
-
-  /**
-   * Add a seriesPath to {@code PTree}.
-   */
-  void addPathToPTree(String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, DOUB_SEPARATOR);
-    if (nodes.length == 0) {
-      throw new PathException();
-    }
-    String rootName = nodes[0];
-    if (ptreeMap.containsKey(rootName)) {
-      PTree ptree = ptreeMap.get(rootName);
-      ptree.addPath(path);
-    } else {
-      throw new MTreePathException("Timeseries's root", rootName);
-    }
-  }
-
-  /**
-   * Delete seriesPath in current MGraph.
-   *
-   * @param path a seriesPath belongs to MTree or PTree
-   */
-  String deletePath(String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, DOUB_SEPARATOR);
-    if (nodes.length == 0) {
-      throw new PathException();
-    }
-    String rootName = nodes[0];
-    if (mtree.getRoot().getName().equals(rootName)) {
-      return mtree.deletePath(path);
-    } else if (ptreeMap.containsKey(rootName)) {
-      PTree ptree = ptreeMap.get(rootName);
-      ptree.deletePath(path);
-      return null;
-    } else {
-      throw new MTreePathException("Timeseries's root", rootName);
-    }
-  }
-
-  /**
-   * Link a {@code MNode} to a {@code PNode} in current PTree.
-   */
-  void linkMNodeToPTree(String path, String mpath) throws PathException {
-    String ptreeName = MetaUtils.getNodeNames(path, DOUB_SEPARATOR)[0];
-    if (!ptreeMap.containsKey(ptreeName)) {
-      throw new MTreePathException("PTree Path", path);
-    } else {
-      ptreeMap.get(ptreeName).linkMNode(path, mpath);
-    }
-  }
-
-  /**
-   * Unlink a {@code MNode} from a {@code PNode} in current PTree.
-   */
-  void unlinkMNodeFromPTree(String path, String mpath) throws PathException {
-    String ptreeName = MetaUtils.getNodeNames(path, DOUB_SEPARATOR)[0];
-    if (!ptreeMap.containsKey(ptreeName)) {
-      throw new MTreePathException("PTree Path", path);
-    } else {
-      ptreeMap.get(ptreeName).unlinkMNode(path, mpath);
-    }
-  }
-
-  /**
-   * Set storage group for current Metadata Tree.
-   *
-   * @param path Format: root.node.(node)*
-   */
-  void setStorageGroup(String path) throws StorageGroupException {
-    mtree.setStorageGroup(path);
-  }
-
-  /**
-   * Delete storage group from current Metadata Tree.
-   *
-   * @param path Format: root.node
-   */
-  void deleteStorageGroup(String path) throws PathException {
-    mtree.deleteStorageGroup(path);
-  }
-
-  /**
-   * Check whether the input path is a storage group for current Metadata Tree or not.
-   *
-   * @param path Format: root.node.(node)*
-   * @apiNote :for cluster
-   */
-  boolean checkStorageGroup(String path) {
-    return mtree.checkStorageGroup(path);
-  }
-
-  /**
-   * Get all paths for given seriesPath regular expression if given seriesPath belongs to MTree, or
-   * get all linked seriesPath for given seriesPath if given seriesPath belongs to PTree Notice:
-   * Regular expression in this method is formed by the amalgamation of seriesPath and the character
-   * '*'.
-   *
-   * @return A HashMap whose Keys are separated by the storage file name.
-   */
-  HashMap<String, List<String>> getAllPathGroupByStorageGroup(String path)
-      throws PathException {
-    String rootName = MetaUtils.getNodeNames(path, DOUB_SEPARATOR)[0];
-    if (mtree.getRoot().getName().equals(rootName)) {
-      return mtree.getAllPath(path);
-    } else if (ptreeMap.containsKey(rootName)) {
-      PTree ptree = ptreeMap.get(rootName);
-      return ptree.getAllLinkedPath(path);
-    }
-    throw new MTreePathException("Timeseries's root", rootName);
-  }
-
-  List<MNode> getAllStorageGroupNodes() {
-    return mtree.getAllStorageGroupNodes();
-  }
-
-  /**
-   * function for getting all timeseries paths under the given seriesPath.
-   */
-  List<List<String>> getShowTimeseriesPath(String path) throws PathException {
-    String rootName = MetaUtils.getNodeNames(path, DOUB_SEPARATOR)[0];
-    if (mtree.getRoot().getName().equals(rootName)) {
-      return mtree.getShowTimeseriesPath(path);
-    } else if (ptreeMap.containsKey(rootName)) {
-      throw new PathException(
-          "PTree is not involved in the execution of the sql 'show timeseries " + path + "'");
-    }
-    throw new MTreePathException("Timeseries's root", rootName);
-  }
-
-  /**
-   * Get all deviceId type in current Metadata Tree.
-   *
-   * @return a HashMap contains all distinct deviceId type separated by deviceId Type
-   */
-  Map<String, List<MeasurementSchema>> getSchemaForAllType() throws PathException {
-    Map<String, List<MeasurementSchema>> res = new HashMap<>();
-    List<String> typeList = mtree.getAllType();
-    for (String type : typeList) {
-      res.put(type, getSchemaForOneType("root." + type));
-    }
-    return res;
-  }
-
-  private ArrayList<String> getDeviceForOneType(String type) throws PathException {
-    return mtree.getDeviceForOneType(type);
-  }
-
-  /**
-   * Get all delta objects group by deviceId type.
-   */
-  private Map<String, List<String>> getDeviceForAllType() throws PathException {
-    Map<String, List<String>> res = new HashMap<>();
-    ArrayList<String> types = mtree.getAllType();
-    for (String type : types) {
-      res.put(type, getDeviceForOneType(type));
-    }
-    return res;
-  }
-
-  /**
-   * Get the full Metadata info.
-   *
-   * @return A {@code Metadata} instance which stores all metadata info
-   */
-  public Metadata getMetadata() throws PathException {
-    Map<String, List<String>> deviceIdMap = getDeviceForAllType();
-    return new Metadata(deviceIdMap);
-  }
-
-  List<String> getAllStorageGroupNames() {
-    return mtree.getAllStorageGroupList();
-  }
-
-  List<String> getAllDevices() throws PathException {
-    return mtree.getAllDevices();
-  }
-
-  public List<String> getDevices(String prefixPath) throws PathException {
-    return mtree.getDevices(prefixPath);
-  }
-
-  List<String> getNodesList(String schemaPattern, int nodeLevel) throws SQLException {
-    return mtree.getNodesList(schemaPattern, nodeLevel);
-  }
-
-  List<String> getLeafNodePathInNextLevel(String path) throws PathException {
-    return mtree.getLeafNodePathInNextLevel(path);
-  }
-  
-  Set<String> getChildNodePathInNextLevel(String path) throws PathException {
-    return mtree.getChildNodePathInNextLevel(path);
-  }
-
-  /**
-   * Get all ColumnSchemas for given delta object type.
-   *
-   * @param path A seriesPath represented one Delta object
-   * @return a list contains all column schema
-   */
-  ArrayList<MeasurementSchema> getSchemaForOneType(String path) throws PathException {
-    return mtree.getSchemaForOneType(path);
-  }
-
-  /**
-   * Get all ColumnSchemas for the storage group seriesPath.
-   *
-   * @param path the Path in a storage group
-   * @return ArrayList<'   ColumnSchema   '> The list of the schema
-   */
-  ArrayList<MeasurementSchema> getSchemaInOneStorageGroup(String path) {
-    return mtree.getSchemaForOneStorageGroup(path);
-  }
-
-  Map<String, MeasurementSchema> getSchemaMapForOneFileNode(String path) {
-    return mtree.getSchemaMapForOneStorageGroup(path);
-  }
-
-  Map<String, Integer> getNumSchemaMapForOneFileNode(String path) {
-    return mtree.getNumSchemaMapForOneFileNode(path);
-  }
-
-  /**
-   * Calculate the count of storage-group nodes included in given seriesPath.
-   *
-   * @return The total count of storage-group nodes.
-   */
-  int getFileCountForOneType(String path) throws PathException {
-    return mtree.getFileCountForOneType(path);
-  }
-
-  /**
-   * Get the file name for given seriesPath Notice: This method could be called if and only if the
-   * seriesPath includes one node whose {@code isStorageGroup} is true.
-   */
-  String getStorageGroupNameByPath(String path) throws StorageGroupException {
-    return mtree.getStorageGroupNameByPath(path);
-  }
-
-  String getStorageGroupNameByPath(MNode node, String path) throws StorageGroupException {
-    return mtree.getStorageGroupNameByPath(node, path);
-  }
-
-  boolean checkStorageGroupByPath(String path) {
-    return mtree.checkFileNameByPath(path);
-  }
-
-  /**
-   * Get all file names for given seriesPath
-   */
-  List<String> getAllStorageGroupNamesByPath(String path) throws PathException {
-    return mtree.getAllFileNamesByPath(path);
-  }
-
-  /**
-   * Check whether the seriesPath given exists.
-   */
-  boolean pathExist(String path) {
-    return mtree.isPathExist(path);
-  }
-
-  boolean pathExist(MNode node, String path) {
-    return mtree.isPathExist(node, path);
-  }
-
-  MNode getNodeByPath(String path) throws PathException {
-    return mtree.getNode(path);
-  }
-
-  MNode getNodeByPathWithCheck(String path) throws PathException, StorageGroupException {
-    return mtree.getNodeByPathWithStorageGroupCheck(path);
-  }
-
-  /**
-   * Get MeasurementSchema for given seriesPath. Notice: Path must be a complete Path from root to
-   * leaf node.
-   */
-  MeasurementSchema getSchemaForOnePath(String path) throws PathException {
-    return mtree.getSchemaForOnePath(path);
-  }
-
-  MeasurementSchema getSchemaForOnePath(MNode node, String path) throws PathException {
-    return mtree.getSchemaForOnePath(node, path);
-  }
-
-  MeasurementSchema getSchemaForOnePathWithCheck(MNode node, String path)
-      throws PathException {
-    return mtree.getSchemaForOnePathWithCheck(node, path);
-  }
-
-  MeasurementSchema getSchemaForOnePathWithCheck(String path) throws PathException {
-    return mtree.getSchemaForOnePathWithCheck(path);
-  }
-
-  /**
-   * functions for converting the mTree to a readable string in json format.
-   */
-  @Override
-  public String toString() {
-    return mtree.toString();
-  }
-
-  /**
-   * combine multiple metadata in string format
-   */
-  static String combineMetadataInStrings(String[] metadataArray) {
-    return MTree.combineMetadataInStrings(metadataArray);
-  }
-
-  /**
-   * @return storage group name -> the series number
-   */
-  Map<String, Integer> countSeriesNumberInEachStorageGroup() throws PathException {
-    Map<String, Integer> res = new HashMap<>();
-    List<String> storageGroups = this.getAllStorageGroupNames();
-    for (String sg : storageGroups) {
-      MNode node = mtree.getNode(sg);
-      res.put(sg, node.getLeafCount());
-    }
-    return res;
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
index 8164bb0..649a267 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
@@ -24,8 +24,8 @@ import java.io.File;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.sql.SQLException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -34,21 +34,20 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import org.apache.iotdb.db.conf.IoTDBConfig;
-import org.apache.iotdb.db.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.conf.adapter.ActiveTimeSeriesCounter;
 import org.apache.iotdb.db.conf.adapter.IoTDBConfigDynamicAdapter;
 import org.apache.iotdb.db.engine.fileSystem.SystemFileFactory;
 import org.apache.iotdb.db.exception.ConfigAdjusterException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.metadata.TimeseriesAlreadyExistException;
-import org.apache.iotdb.db.exception.path.MTreePathException;
-import org.apache.iotdb.db.exception.path.NotStorageGroupException;
-import org.apache.iotdb.db.exception.path.PathException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
+import org.apache.iotdb.db.exception.metadata.PathNotExistException;
+import org.apache.iotdb.db.exception.metadata.StorageGroupNotSetException;
+import org.apache.iotdb.db.metadata.mnode.MNode;
+import org.apache.iotdb.db.metadata.mnode.StorageGroupMNode;
 import org.apache.iotdb.db.monitor.MonitorConstants;
 import org.apache.iotdb.db.qp.constant.SQLConstant;
 import org.apache.iotdb.db.utils.RandomDeleteCache;
+import org.apache.iotdb.db.utils.TestOnly;
 import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
 import org.apache.iotdb.tsfile.exception.cache.CacheException;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
@@ -67,67 +66,50 @@ import org.slf4j.LoggerFactory;
 public class MManager {
 
   private static final Logger logger = LoggerFactory.getLogger(MManager.class);
-  private static final String DOUB_SEPARATOR = "\\.";
-  private static final String ROOT_NAME = MetadataConstant.ROOT;
   private static final String TIME_SERIES_TREE_HEADER = "===  Timeseries Tree  ===\n\n";
 
   // the lock for read/insert
   private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
   // the log file seriesPath
   private String logFilePath;
-  private MGraph mgraph;
+  private MTree mtree;
   private BufferedWriter logWriter;
   private boolean writeToLog;
   private String schemaDir;
-
-  private RandomDeleteCache<String, PathCheckRet> checkAndGetDataTypeCache;
+  // path -> MNode
   private RandomDeleteCache<String, MNode> mNodeCache;
 
   private Map<String, Integer> seriesNumberInStorageGroups = new HashMap<>();
   private long maxSeriesNumberAmongStorageGroup;
   private boolean initialized;
+  private IoTDBConfig config;
 
   private MManager() {
-
-    schemaDir =
-        IoTDBDescriptor.getInstance().getConfig().getSchemaDir();
-
-    File systemFolder = SystemFileFactory.INSTANCE.getFile(schemaDir);
-    if (!systemFolder.exists()) {
-      if (systemFolder.mkdirs()) {
-        logger.info("create system folder {}", systemFolder.getAbsolutePath());
+    config = IoTDBDescriptor.getInstance().getConfig();
+    schemaDir = config.getSchemaDir();
+    File schemaFolder = SystemFileFactory.INSTANCE.getFile(schemaDir);
+    if (!schemaFolder.exists()) {
+      if (schemaFolder.mkdirs()) {
+        logger.info("create system folder {}", schemaFolder.getAbsolutePath());
       } else {
-        logger.info("create system folder {} failed.", systemFolder.getAbsolutePath());
+        logger.info("create system folder {} failed.", schemaFolder.getAbsolutePath());
       }
     }
     logFilePath = schemaDir + File.separator + MetadataConstant.METADATA_LOG;
     writeToLog = false;
 
-    int cacheSize = IoTDBDescriptor.getInstance().getConfig().getmManagerCacheSize();
-    checkAndGetDataTypeCache = new RandomDeleteCache<String, PathCheckRet>(cacheSize) {
-      @Override
-      public void beforeRemove(PathCheckRet object) {
-        //allowed to do nothing
-      }
-
-      @Override
-      public PathCheckRet loadObjectByKey(String key) throws CacheException {
-        return loadPathToCache(key);
-      }
-    };
-
+    int cacheSize = config.getmManagerCacheSize();
     mNodeCache = new RandomDeleteCache<String, MNode>(cacheSize) {
-      @Override
-      public void beforeRemove(MNode object) {
-        //allowed to do nothing
-      }
 
       @Override
       public MNode loadObjectByKey(String key) throws CacheException {
+        lock.readLock().lock();
         try {
-          return getNodeByPathWithCheck(key);
-        } catch (PathException | StorageGroupException e) {
+          return mtree.getNodeByPathWithStorageGroupCheck(key);
+        } catch (MetadataException e) {
           throw new CacheException(e);
+        } finally {
+          lock.readLock().unlock();
         }
       }
     };
@@ -140,7 +122,6 @@ public class MManager {
   //Because the writer will be used later and should not be closed here.
   @SuppressWarnings("squid:S2093")
   public void init() {
-
     if (initialized) {
       return;
     }
@@ -149,7 +130,15 @@ public class MManager {
 
     try {
       initFromLog(logFile);
-      seriesNumberInStorageGroups = mgraph.countSeriesNumberInEachStorageGroup();
+
+      // storage group name -> the series number
+      seriesNumberInStorageGroups = new HashMap<>();
+      List<String> storageGroups = mtree.getAllStorageGroupNames();
+      for (String sg : storageGroups) {
+        MNode node = mtree.getNodeByPath(sg);
+        seriesNumberInStorageGroups.put(sg, node.getLeafCount());
+      }
+
       if (seriesNumberInStorageGroups.isEmpty()) {
         maxSeriesNumberAmongStorageGroup = 0;
       } else {
@@ -157,20 +146,18 @@ public class MManager {
             .max(Integer::compareTo).get();
       }
       writeToLog = true;
-    } catch (PathException | IOException | MetadataException e) {
-      mgraph = new MGraph(ROOT_NAME);
-      logger.error("Cannot read MGraph from file, using an empty new one", e);
+    } catch (IOException | MetadataException e) {
+      mtree = new MTree();
+      logger.error("Cannot read MTree from file, using an empty new one", e);
     } finally {
       lock.writeLock().unlock();
     }
     initialized = true;
   }
 
-
-  private void initFromLog(File logFile)
-      throws IOException, PathException, MetadataException {
+  private void initFromLog(File logFile) throws IOException, MetadataException {
     // init the metadata from the operation log
-    mgraph = new MGraph(ROOT_NAME);
+    mtree = new MTree();
     if (logFile.exists()) {
       try (FileReader fr = new FileReader(logFile);
           BufferedReader br = new BufferedReader(fr)) {
@@ -183,13 +170,12 @@ public class MManager {
   }
 
   /**
-   * function for clearing MGraph.
+   * function for clearing MTree
    */
   public void clear() {
     lock.writeLock().lock();
     try {
-      this.mgraph = new MGraph(ROOT_NAME);
-      this.checkAndGetDataTypeCache.clear();
+      this.mtree = new MTree();
       this.mNodeCache.clear();
       this.seriesNumberInStorageGroups.clear();
       this.maxSeriesNumberAmongStorageGroup = 0;
@@ -204,12 +190,11 @@ public class MManager {
     }
   }
 
-  public void operation(String cmd)
-      throws PathException, IOException, MetadataException {
-    //see addPathToMTree() to get the detailed format of the cmd
+  public void operation(String cmd) throws IOException, MetadataException {
+    //see createTimeseries() to get the detailed format of the cmd
     String[] args = cmd.trim().split(",");
     switch (args[0]) {
-      case MetadataOperationType.ADD_PATH_TO_MTREE:
+      case MetadataOperationType.CREATE_TIMESERIES:
         Map<String, String> props = null;
         if (args.length > 5) {
           String[] kv;
@@ -220,38 +205,21 @@ public class MManager {
           }
         }
 
-        addPathToMTree(new Path(args[1]), TSDataType.deserialize(Short.parseShort(args[2])),
+        createTimeseries(args[1], TSDataType.deserialize(Short.parseShort(args[2])),
             TSEncoding.deserialize(Short.parseShort(args[3])),
             CompressionType.deserialize(Short.parseShort(args[4])),
             props);
         break;
-      case MetadataOperationType.DELETE_PATH_FROM_MTREE:
-        deletePaths(Collections.singletonList(new Path(args[1])), false);
-        break;
-      case MetadataOperationType.SET_STORAGE_GROUP_TO_MTREE:
-        setStorageGroupToMTree(args[1]);
-        break;
-      case MetadataOperationType.DELETE_STORAGE_GROUP_FROM_MTREE:
-        List<Path> storageGroups = new ArrayList<>();
-        for (int l = 1; l < args.length; l++) {
-          storageGroups.add(new Path(args[l]));
-        }
-        deleteStorageGroupsFromMTree(storageGroups);
-        break;
-      case MetadataOperationType.ADD_A_PTREE:
-        addAPTree(args[1]);
-        break;
-      case MetadataOperationType.ADD_A_PATH_TO_PTREE:
-        addPathToPTree(args[1]);
+      case MetadataOperationType.DELETE_TIMESERIES:
+        deleteTimeseries(args[1]);
         break;
-      case MetadataOperationType.DELETE_PATH_FROM_PTREE:
-        deletePathFromPTree(args[1]);
+      case MetadataOperationType.SET_STORAGE_GROUP:
+        setStorageGroup(args[1]);
         break;
-      case MetadataOperationType.LINK_MNODE_TO_PTREE:
-        linkMNodeToPTree(args[1], args[2]);
-        break;
-      case MetadataOperationType.UNLINK_MNODE_FROM_PTREE:
-        unlinkMNodeFromPTree(args[1], args[2]);
+      case MetadataOperationType.DELETE_STORAGE_GROUP:
+        List<String> storageGroups = new ArrayList<>();
+        storageGroups.addAll(Arrays.asList(args).subList(1, args.length));
+        deleteStorageGroups(storageGroups);
         break;
       case MetadataOperationType.SET_TTL:
         setTTL(args[1], Long.parseLong(args[2]));
@@ -279,307 +247,192 @@ public class MManager {
     return logWriter;
   }
 
-  public boolean addPathToMTree(String path, TSDataType dataType, TSEncoding encoding,
-      CompressionType compressor, Map<String, String> props)
-      throws MetadataException, PathException {
-    return addPathToMTree(new Path(path), dataType, encoding, compressor, props);
-  }
-
   /**
-   * <p> Add one timeseries to metadata tree.
+   * Add one timeseries to metadata tree, if the timeseries already exists, throw exception
    *
-   * @param path the timeseries seriesPath
-   * @param dataType the dateType {@code DataType} for the timeseries
-   * @param encoding the encoding function {@code Encoding} for the timeseries
-   * @param compressor the compressor function {@code Compressor} for the time series
+   * @param path the timeseries path
+   * @param dataType the dateType {@code DataType} of the timeseries
+   * @param encoding the encoding function {@code Encoding} of the timeseries
+   * @param compressor the compressor function {@code Compressor} of the time series
    * @return whether the measurement occurs for the first time in this storage group (if true, the
    * measurement should be registered to the StorageEngine too)
    */
-  @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
-  public boolean addPathToMTree(Path path, TSDataType dataType, TSEncoding encoding,
-      CompressionType compressor, Map<String, String> props)
-      throws MetadataException, PathException {
+  public boolean createTimeseries(String path, TSDataType dataType, TSEncoding encoding,
+      CompressionType compressor, Map<String, String> props) throws MetadataException {
     lock.writeLock().lock();
     try {
-      if (pathExist(path.getFullPath())) {
-        throw new TimeseriesAlreadyExistException(path.getFullPath());
-      }
-      IoTDBConfig conf = IoTDBDescriptor.getInstance().getConfig();
-      if (!checkStorageGroupByPath(path.getFullPath())) {
-        if (!conf.isAutoCreateSchemaEnabled()) {
-          throw new MetadataException("Storage group should be created first");
-        }
-        String storageGroupName = getStorageGroupNameByAutoLevel(
-            path.getFullPath(), conf.getDefaultStorageGroupLevel());
-        setStorageGroupToMTree(storageGroupName);
-      }
-      // optimize the speed of adding timeseries
-      String fileNodePath;
+      /*
+       * get the storage group with auto create schema
+       */
+      String storageGroupName;
       try {
-        fileNodePath = getStorageGroupNameByPath(path.getFullPath());
-      } catch (StorageGroupException e) {
-        throw new MetadataException(e);
+        storageGroupName = mtree.getStorageGroupName(path);
+      } catch (StorageGroupNotSetException e) {
+        if (!config.isAutoCreateSchemaEnabled()) {
+          throw e;
+        }
+        storageGroupName = MetaUtils.getStorageGroupNameByLevel(path,
+            config.getDefaultStorageGroupLevel());
+        setStorageGroup(storageGroupName);
       }
-      // the two map is stored in the storage group node
-      Map<String, MeasurementSchema> schemaMap = getStorageGroupSchemaMap(fileNodePath);
-      Map<String, Integer> numSchemaMap = getStorageGroupNumSchemaMap(fileNodePath);
-      String lastNode = path.getMeasurement();
+
+      /*
+       * check if the measurement schema conflict in its storage group
+       */
+      Map<String, MeasurementSchema> schemaMap = mtree.getStorageGroupSchemaMap(storageGroupName);
+      String measurement = new Path(path).getMeasurement();
       boolean isNewMeasurement = true;
-      // Thread safety: just one thread can access/modify the schemaMap
-      synchronized (schemaMap) {
-        // Need to check the path again to avoid duplicated inserting by multi concurrent threads
-        if (pathExist(path.getFullPath())) {
-          throw new TimeseriesAlreadyExistException(path.getFullPath());
-        }
-        if (schemaMap.containsKey(lastNode)) {
-          isNewMeasurement = false;
-          MeasurementSchema columnSchema = schemaMap.get(lastNode);
-          if (!columnSchema.getType().equals(dataType)
-              || !columnSchema.getEncodingType().equals(encoding)
-              || !columnSchema.getCompressor().equals(compressor)) {
-            throw new MetadataException(String.format(
-                "The resultDataType or encoding or compression of the last node %s is conflicting "
-                    + "in the storage group %s", lastNode, fileNodePath));
-          }
-          try {
-            addPathToMTreeInternal(path.getFullPath(), dataType, encoding, compressor, props);
-          } catch (PathException | StorageGroupException e) {
-            throw new MetadataException(e);
-          } catch (IOException e) {
-            throw new MetadataException(e.getMessage());
-          }
-          numSchemaMap.put(lastNode, numSchemaMap.get(lastNode) + 1);
-        } else {
-          try {
-            addPathToMTreeInternal(path.getFullPath(), dataType, encoding, compressor, props);
-          } catch (PathException | StorageGroupException e) {
-            throw new MetadataException(e);
-          } catch (IOException e) {
-            throw new MetadataException(e.getMessage());
-          }
-          MeasurementSchema columnSchema;
-          try {
-            columnSchema = getSchemaForOnePath(path.toString());
-          } catch (PathException e) {
-            throw new MetadataException(e);
-          }
-          schemaMap.put(lastNode, columnSchema);
-          numSchemaMap.put(lastNode, 1);
-        }
-        try {
-          IoTDBConfigDynamicAdapter.getInstance().addOrDeleteTimeSeries(1);
-        } catch (ConfigAdjusterException e) {
-          // Undo create time series
-          deletePaths(Collections.singletonList(path), true);
-          throw new MetadataException(e);
+      if (schemaMap.containsKey(measurement)) {
+        isNewMeasurement = false;
+        MeasurementSchema schema = schemaMap.get(measurement);
+        if (!schema.getType().equals(dataType) || !schema.getEncodingType().equals(encoding)
+            || !schema.getCompressor().equals(compressor)) {
+          // conflict with existing
+          throw new MetadataException(String.format(
+              "The resultDataType or encoding or compression of the last node %s is conflicting "
+                  + "in the storage group %s", measurement, storageGroupName));
         }
-        return isNewMeasurement;
       }
-    } finally {
-      lock.writeLock().unlock();
-    }
-  }
 
-  /**
-   * path will be added to mgraph with no check
-   */
-  private void addPathToMTreeInternal(String path, TSDataType dataType, TSEncoding encoding,
-      CompressionType compressor, Map<String, String> props)
-      throws PathException, IOException, StorageGroupException {
-
-    mgraph.addPathToMTree(path, dataType, encoding, compressor, props);
-    String storageGroupName = mgraph.getStorageGroupNameByPath(path);
-    int size = seriesNumberInStorageGroups.get(storageGroupName);
-    seriesNumberInStorageGroups.put(storageGroupName, size + 1);
-    if (size + 1 > maxSeriesNumberAmongStorageGroup) {
-      maxSeriesNumberAmongStorageGroup = size + 1;
-    }
-    if (writeToLog) {
-      BufferedWriter writer = getLogWriter();
-      writer.write(String.format("%s,%s,%s,%s,%s", MetadataOperationType.ADD_PATH_TO_MTREE,
-          path, dataType.serialize(), encoding.serialize(), compressor.serialize()));
-      if (props != null) {
-        for (Map.Entry entry : props.entrySet()) {
-          writer.write(String.format(",%s=%s", entry.getKey(), entry.getValue()));
-        }
+      // create time series with memory check
+      createTimeseriesWithMemoryCheckAndLog(path, dataType, encoding, compressor, props);
+      // register schema in this storage group
+      if (isNewMeasurement) {
+        schemaMap.put(measurement,
+            new MeasurementSchema(measurement, dataType, encoding, compressor, props));
+      }
+      // update statistics
+      int size = seriesNumberInStorageGroups.get(storageGroupName);
+      seriesNumberInStorageGroups.put(storageGroupName, size + 1);
+      if (size + 1 > maxSeriesNumberAmongStorageGroup) {
+        maxSeriesNumberAmongStorageGroup = size + 1;
       }
-      writer.newLine();
-      writer.flush();
+      return isNewMeasurement;
+    } finally {
+      lock.writeLock().unlock();
     }
   }
 
-  /**
-   * <p> Add one timeseries to metadata. Must invoke the<code>pathExist</code> and
-   * <code>getStorageGroupNameByPath</code> method first to check timeseries. </p>
-   *
-   * this is just for compatibility  TEST ONLY
-   *
-   * @param path the timeseries seriesPath
-   * @param dataType the dateType {@code DataType} for the timeseries
-   * @param encoding the encoding function {@code Encoding} for the timeseries
-   */
-  public void addPathToMTree(String path, String dataType, String encoding)
-      throws PathException, IOException, StorageGroupException {
+  @TestOnly
+  public void createTimeseries(String path, String dataType, String encoding)
+      throws MetadataException {
     lock.writeLock().lock();
     try {
       TSDataType tsDataType = TSDataType.valueOf(dataType);
       TSEncoding tsEncoding = TSEncoding.valueOf(encoding);
-      CompressionType type = CompressionType
-          .valueOf(TSFileDescriptor.getInstance().getConfig().getCompressor());
-      addPathToMTreeInternal(path, tsDataType, tsEncoding, type, Collections.emptyMap());
+      CompressionType type = TSFileDescriptor.getInstance().getConfig().getCompressor();
+      createTimeseriesWithMemoryCheckAndLog(path, tsDataType, tsEncoding, type,
+          Collections.emptyMap());
     } finally {
       lock.writeLock().unlock();
     }
   }
 
   /**
-   * <p> Add one <code>deviceId</code> to metadata.</p>
-   *
-   * This is available IF and ONLY IF creating schema automatically is enabled.
-   *
-   * @param deviceId the deviceId of a timeseries seriesPath
+   * timeseries will be added to MTree with check memory, and log to file
    */
-  private MNode addDeviceIdToMTree(String deviceId) throws PathException {
-    lock.writeLock().lock();
+  private void createTimeseriesWithMemoryCheckAndLog(String timeseries, TSDataType dataType,
+      TSEncoding encoding, CompressionType compressor, Map<String, String> props)
+      throws MetadataException {
+    mtree.createTimeseries(timeseries, dataType, encoding, compressor, props);
     try {
-      return mgraph.addDeviceIdToMTree(deviceId);
-    } finally {
-      lock.writeLock().unlock();
+      // check memory
+      IoTDBConfigDynamicAdapter.getInstance().addOrDeleteTimeSeries(1);
+    } catch (ConfigAdjusterException e) {
+      mtree.deleteTimeseriesAndReturnEmptyStorageGroup(timeseries);
+      throw new MetadataException(e);
     }
-  }
-
-  private List<String> collectPaths(List<Path> paths) throws MetadataException {
-    Set<String> pathSet = new HashSet<>();
-    // Attention: Monitor storage group seriesPath is not allowed to be deleted
-    for (Path p : paths) {
-      List<String> subPaths;
-      subPaths = getPaths(p.getFullPath());
-      if (subPaths.isEmpty()) {
-        throw new MetadataException(String
-            .format("There are no timeseries in the prefix of %s seriesPath",
-                p.getFullPath()));
-      }
-      List<String> newSubPaths = new ArrayList<>();
-      for (String eachSubPath : subPaths) {
-        String storageGroupName;
-        try {
-          storageGroupName = getStorageGroupNameByPath(eachSubPath);
-        } catch (StorageGroupException e) {
-          throw new MetadataException(e);
-        }
-
-        if (MonitorConstants.STAT_STORAGE_GROUP_PREFIX.equals(storageGroupName)) {
-          continue;
+    try {
+      if (writeToLog) {
+        BufferedWriter writer = getLogWriter();
+        writer.write(String.format("%s,%s,%s,%s,%s", MetadataOperationType.CREATE_TIMESERIES,
+            timeseries, dataType.serialize(), encoding.serialize(), compressor.serialize()));
+        if (props != null) {
+          for (Map.Entry entry : props.entrySet()) {
+            writer.write(String.format(",%s=%s", entry.getKey(), entry.getValue()));
+          }
         }
-        newSubPaths.add(eachSubPath);
-      }
-      pathSet.addAll(newSubPaths);
-    }
-    for (String p : pathSet) {
-      if (!pathExist(p)) {
-        throw new MetadataException(String.format(
-            "Timeseries %s does not exist and cannot be deleted", p));
+        writer.newLine();
+        writer.flush();
       }
+    } catch (IOException e) {
+      throw new MetadataException(e.getMessage());
     }
-    return new ArrayList<>(pathSet);
   }
 
   /**
-   * delete given paths from metadata.
+   * Delete all timeseries under the given path, may cross different storage group
    *
-   * @param deletePathList list of paths to be deleted
+   * @param prefixPath path to be deleted, could be root or a prefix path or a full path
    * @return a set contains StorageGroups that contain no more timeseries after this deletion and
    * files of such StorageGroups should be deleted to reclaim disk space.
    */
-  public Set<String> deletePaths(List<Path> deletePathList, boolean isUndo)
-      throws MetadataException {
-    if (deletePathList != null && !deletePathList.isEmpty()) {
-      List<String> fullPath = collectPaths(deletePathList);
-
-      Set<String> emptyStorageGroups = new HashSet<>();
-      for (String p : fullPath) {
-        if (!isUndo) {
-          try {
-            IoTDBConfigDynamicAdapter.getInstance().addOrDeleteTimeSeries(-1);
-          } catch (ConfigAdjusterException e) {
-            throw new MetadataException(e);
-          }
-        }
-        String emptiedStorageGroup = deletePath(p);
-        if (emptiedStorageGroup != null) {
-          emptyStorageGroups.add(emptiedStorageGroup);
-        }
-      }
-      return emptyStorageGroups;
-    }
-    return Collections.emptySet();
-  }
-
-  private String deletePath(String pathStr) throws MetadataException {
-    String storageGroupName;
-    try {
-      storageGroupName = getStorageGroupNameByPath(pathStr);
-    } catch (StorageGroupException e) {
-      throw new MetadataException(e);
-    }
-    String emptiedStorageGroup;
-    // the two maps are stored in the storage group node
-    Map<String, MeasurementSchema> schemaMap = getStorageGroupSchemaMap(storageGroupName);
-    Map<String, Integer> numSchemaMap = getStorageGroupNumSchemaMap(storageGroupName);
-    // Thread safety: just one thread can access/modify the schemaMap
-    synchronized (schemaMap) {
-      // TODO: don't delete the storage group seriesPath recursively
-      Path path = new Path(pathStr);
-      String measurementId = path.getMeasurement();
-      if (numSchemaMap.get(measurementId) == 1) {
-        numSchemaMap.remove(measurementId);
-        schemaMap.remove(measurementId);
-      } else {
-        numSchemaMap.put(measurementId, numSchemaMap.get(measurementId) - 1);
+  public Set<String> deleteTimeseries(String prefixPath) throws MetadataException {
+    lock.writeLock().lock();
+    if (isStorageGroup(prefixPath)) {
+      int size = seriesNumberInStorageGroups.get(prefixPath);
+      seriesNumberInStorageGroups.put(prefixPath, 0);
+      if (size == maxSeriesNumberAmongStorageGroup) {
+        seriesNumberInStorageGroups.values().stream().max(Integer::compareTo)
+            .ifPresent(val -> maxSeriesNumberAmongStorageGroup = val);
       }
       try {
-        emptiedStorageGroup = deletePathFromMTree(pathStr);
-      } catch (PathException | StorageGroupException e) {
-        throw new MetadataException(e);
-      } catch (IOException e) {
+        IoTDBConfigDynamicAdapter.getInstance()
+            .addOrDeleteTimeSeries(seriesNumberInStorageGroups.remove(prefixPath) * (-1));
+      } catch (ConfigAdjusterException e) {
         throw new MetadataException(e.getMessage());
       }
+      mNodeCache.clear();
+    }
+    try {
+      Set<String> emptyStorageGroups = new HashSet<>();
+
+      List<String> allTimeseries = mtree.getAllTimeseriesName(prefixPath);
+      // Monitor storage group seriesPath is not allowed to be deleted
+      allTimeseries.removeIf(p -> p.startsWith(MonitorConstants.STAT_STORAGE_GROUP_PREFIX));
+
+      for (String p : allTimeseries) {
+        String emptyStorageGroup = deleteOneTimeseriesAndUpdateStatisticsAndLog(p);
+        if (emptyStorageGroup != null) {
+          emptyStorageGroups.add(emptyStorageGroup);
+        }
+      }
+      return emptyStorageGroups;
+    } catch (IOException e) {
+      throw new MetadataException(e.getMessage());
+    } finally {
+      lock.writeLock().unlock();
     }
-    return emptiedStorageGroup;
   }
 
   /**
-   * function for deleting a given path from mTree.
-   *
-   * @return the related storage group name if there is no path in the storage group anymore;
-   * otherwise null
+   * @param path full path from root to leaf node
+   * @return after delete if the storage group is empty, return its name, otherwise return null
    */
-  private String deletePathFromMTree(String path)
-      throws PathException, IOException, StorageGroupException {
+  private String deleteOneTimeseriesAndUpdateStatisticsAndLog(String path)
+      throws MetadataException, IOException {
     lock.writeLock().lock();
     try {
-      checkAndGetDataTypeCache.clear();
-      mNodeCache.clear();
-      String storageGroupName = mgraph.deletePath(path);
       if (writeToLog) {
         BufferedWriter writer = getLogWriter();
-        writer.write(MetadataOperationType.DELETE_PATH_FROM_MTREE + "," + path);
+        writer.write(MetadataOperationType.DELETE_TIMESERIES + "," + path);
         writer.newLine();
         writer.flush();
       }
-      String storageGroup = getStorageGroupNameByPath(path);
+      String storageGroupName = mtree.deleteTimeseriesAndReturnEmptyStorageGroup(path);
+      // TODO: delete the path node and all its ancestors
+      mNodeCache.clear();
+      try {
+        IoTDBConfigDynamicAdapter.getInstance().addOrDeleteTimeSeries(-1);
+      } catch (ConfigAdjusterException e) {
+        throw new MetadataException(e);
+      }
+      String storageGroup = getStorageGroupName(path);
       int size = seriesNumberInStorageGroups.get(storageGroup);
       seriesNumberInStorageGroups.put(storageGroup, size - 1);
       if (size == maxSeriesNumberAmongStorageGroup) {
-        //recalculate
-        if (seriesNumberInStorageGroups.isEmpty()) {
-          maxSeriesNumberAmongStorageGroup = 0;
-        } else {
-          maxSeriesNumberAmongStorageGroup = seriesNumberInStorageGroups.values().stream()
-              .max(Integer::compareTo).get();
-        }
-      } else {
-        maxSeriesNumberAmongStorageGroup--;
+        seriesNumberInStorageGroups.values().stream().max(Integer::compareTo)
+            .ifPresent(val -> maxSeriesNumberAmongStorageGroup = val);
       }
       return storageGroupName;
     } finally {
@@ -588,77 +441,73 @@ public class MManager {
   }
 
   /**
-   * function for setting storage group of the given path to mTree.
+   * Set storage group of the given path to MTree. Check
+   *
+   * @param storageGroup root.node.(node)*
    */
-  public void setStorageGroupToMTree(String path) throws MetadataException {
+  public void setStorageGroup(String storageGroup) throws MetadataException {
     lock.writeLock().lock();
     try {
-      if (mgraph.checkStorageGroup(path)) {
-        return;
-      }
-      mgraph.setStorageGroup(path);
-      IoTDBConfigDynamicAdapter.getInstance().addOrDeleteStorageGroup(1);
-      ActiveTimeSeriesCounter.getInstance().init(path);
-      seriesNumberInStorageGroups.put(path, 0);
       if (writeToLog) {
         BufferedWriter writer = getLogWriter();
-        writer.write(MetadataOperationType.SET_STORAGE_GROUP_TO_MTREE + "," + path);
+        writer.write(MetadataOperationType.SET_STORAGE_GROUP + "," + storageGroup);
         writer.newLine();
         writer.flush();
       }
-    } catch (StorageGroupException e) {
-      throw new MetadataException(e);
+      mtree.setStorageGroup(storageGroup);
+      IoTDBConfigDynamicAdapter.getInstance().addOrDeleteStorageGroup(1);
+      ActiveTimeSeriesCounter.getInstance().init(storageGroup);
+      seriesNumberInStorageGroups.put(storageGroup, 0);
     } catch (IOException e) {
       throw new MetadataException(e.getMessage());
     } catch (ConfigAdjusterException e) {
-      try {
-        mgraph.deleteStorageGroup(path);
-        throw new MetadataException(e);
-      } catch (PathException ex) {
-        throw new MetadataException(ex);
-      }
+      mtree.deleteStorageGroup(storageGroup);
+      throw new MetadataException(e);
     } finally {
       lock.writeLock().unlock();
     }
   }
 
   /**
-   * function for deleting storage groups of the given path from mTree. the log format is like
-   * "delete_storage_group,sg1,sg2,sg3" TODO: return value unused
+   * Delete storage groups of given paths from MTree. Log format: "delete_storage_group,sg1,sg2,sg3"
+   *
+   * @param storageGroups list of paths to be deleted. Format: root.node
    */
-  public boolean deleteStorageGroupsFromMTree(List<Path> deletePathList)
-      throws MetadataException {
-    List<String> pathList = new ArrayList<>();
-    StringBuilder jointPath = new StringBuilder();
-    for (Path storagePath : deletePathList) {
-      pathList.add(storagePath.getFullPath());
-      jointPath.append(",").append(storagePath.getFullPath());
-    }
+  public void deleteStorageGroups(List<String> storageGroups) throws MetadataException {
     lock.writeLock().lock();
     try {
       if (writeToLog) {
+        StringBuilder jointPath = new StringBuilder();
+        for (String storagePath : storageGroups) {
+          jointPath.append(",").append(storagePath);
+        }
         BufferedWriter writer = getLogWriter();
-        writer.write(MetadataOperationType.DELETE_STORAGE_GROUP_FROM_MTREE + jointPath);
+        writer.write(MetadataOperationType.DELETE_STORAGE_GROUP + jointPath);
         writer.newLine();
         writer.flush();
       }
-      for (String delStorageGroup : pathList) {
+      for (String storageGroup : storageGroups) {
         try {
-          checkAndGetDataTypeCache.clear();
-          mNodeCache.clear();
-          IoTDBConfigDynamicAdapter.getInstance().addOrDeleteStorageGroup(-1);
-          mgraph.deleteStorageGroup(delStorageGroup);
-          IoTDBConfigDynamicAdapter.getInstance()
-              .addOrDeleteTimeSeries(seriesNumberInStorageGroups.remove(delStorageGroup) * (-1));
-          ActiveTimeSeriesCounter.getInstance().delete(delStorageGroup);
-        } catch (PathException e) {
-          try {
-            IoTDBConfigDynamicAdapter.getInstance().addOrDeleteStorageGroup(1);
-          } catch (ConfigAdjusterException ex) {
-            throw new MetadataException(ex);
-          }
+          // try to delete storage group
+          mtree.deleteStorageGroup(storageGroup);
+        } catch (MetadataException e) {
+          IoTDBConfigDynamicAdapter.getInstance().addOrDeleteStorageGroup(1);
           throw new MetadataException(e);
         }
+        mNodeCache.clear();
+        IoTDBConfigDynamicAdapter.getInstance().addOrDeleteStorageGroup(-1);
+        int size = seriesNumberInStorageGroups.get(storageGroup);
+        IoTDBConfigDynamicAdapter.getInstance().addOrDeleteTimeSeries(size * -1);
+        ActiveTimeSeriesCounter.getInstance().delete(storageGroup);
+        seriesNumberInStorageGroups.remove(storageGroup);
+        if (size == maxSeriesNumberAmongStorageGroup) {
+          if (seriesNumberInStorageGroups.isEmpty()) {
+            maxSeriesNumberAmongStorageGroup = 0;
+          } else {
+            maxSeriesNumberAmongStorageGroup = seriesNumberInStorageGroups.values().stream()
+                .max(Integer::compareTo).get();
+          }
+        }
       }
     } catch (ConfigAdjusterException e) {
       throw new MetadataException(e);
@@ -667,813 +516,329 @@ public class MManager {
     } finally {
       lock.writeLock().unlock();
     }
-    return true;
   }
 
   /**
-   * function for checking if the given path is storage group of mTree or not.
+   * Check if the given path is storage group or not.
    *
+   * @param path Format: root.node.(node)*
    * @apiNote :for cluster
    */
-  boolean checkStorageGroupOfMTree(String path) {
+  boolean isStorageGroup(String path) {
     lock.readLock().lock();
     try {
-      return mgraph.checkStorageGroup(path);
+      return mtree.isStorageGroup(path);
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * function for adding a pTree.
-   */
-  public void addAPTree(String ptreeRootName) throws IOException, MetadataException {
-
-    lock.writeLock().lock();
-    try {
-      mgraph.addAPTree(ptreeRootName);
-      if (writeToLog) {
-        BufferedWriter writer = getLogWriter();
-        writer.write(MetadataOperationType.ADD_A_PTREE + "," + ptreeRootName);
-        writer.newLine();
-        writer.flush();
-      }
-    } finally {
-      lock.writeLock().unlock();
-    }
-  }
-
-  /**
-   * function for adding a given path to pTree.
-   */
-  public void addPathToPTree(String path)
-      throws PathException, IOException {
-
-    lock.writeLock().lock();
-    try {
-      mgraph.addPathToPTree(path);
-      if (writeToLog) {
-        BufferedWriter writer = getLogWriter();
-        writer.write(MetadataOperationType.ADD_A_PATH_TO_PTREE + "," + path);
-        writer.newLine();
-        writer.flush();
-      }
-    } finally {
-      lock.writeLock().unlock();
-    }
-  }
-
-  /**
-   * function for deleting a given path from pTree.
+   * Get series type for given seriesPath.
+   *
+   * @param path full path
    */
-  public void deletePathFromPTree(String path) throws PathException, IOException {
-
-    lock.writeLock().lock();
+  public TSDataType getSeriesType(String path) throws MetadataException {
+    lock.readLock().lock();
     try {
-      mgraph.deletePath(path);
-      if (writeToLog) {
-        BufferedWriter writer = getLogWriter();
-        writer.write(MetadataOperationType.DELETE_PATH_FROM_PTREE + "," + path);
-        writer.newLine();
-        writer.flush();
+      if (path.equals(SQLConstant.RESERVED_TIME)) {
+        return TSDataType.INT64;
       }
+      return mtree.getSchema(path).getType();
     } finally {
-      lock.writeLock().unlock();
+      lock.readLock().unlock();
     }
   }
 
-  /**
-   * function for linking MNode to pTree.
-   */
-  public void linkMNodeToPTree(String path, String mpath) throws PathException, IOException {
-
-    lock.writeLock().lock();
-    try {
-      mgraph.linkMNodeToPTree(path, mpath);
-      if (writeToLog) {
-        BufferedWriter writer = getLogWriter();
-        writer.write(MetadataOperationType.LINK_MNODE_TO_PTREE + "," + path + "," + mpath);
-        writer.newLine();
-        writer.flush();
-      }
-    } finally {
-      lock.writeLock().unlock();
-    }
-  }
 
   /**
-   * function for unlinking MNode from pTree.
+   * Get all devices under given prefixPath.
+   *
+   * @param prefixPath a prefix of a full path. if the wildcard is not at the tail, then each
+   * wildcard can only match one level, otherwise it can match to the tail.
+   * @return A HashSet instance which stores devices names with given prefixPath.
    */
-  public void unlinkMNodeFromPTree(String path, String mpath)
-      throws PathException, IOException {
-
-    lock.writeLock().lock();
+  public List<String> getDevices(String prefixPath) throws MetadataException {
+    lock.readLock().lock();
     try {
-      mgraph.unlinkMNodeFromPTree(path, mpath);
-      if (writeToLog) {
-        BufferedWriter writer = getLogWriter();
-        writer.write(MetadataOperationType.UNLINK_MNODE_FROM_PTREE + "," + path + "," + mpath);
-        writer.newLine();
-        writer.flush();
-      }
+      return mtree.getDevices(prefixPath);
     } finally {
-      lock.writeLock().unlock();
+      lock.readLock().unlock();
     }
   }
 
   /**
-   * Get series type for given seriesPath.
+   * Get all nodes from the given level
    *
-   * @return TSDataType
+   * @param prefixPath can be a prefix of a full path. Can not be a full path. can not have
+   * wildcard. But, the level of the prefixPath can be smaller than the given level, e.g.,
+   * prefixPath = root.a while the given level is 5
+   * @param nodeLevel the level can not be smaller than the level of the prefixPath
+   * @return A List instance which stores all node at given level
    */
-  public TSDataType getSeriesType(String fullPath) throws PathException {
-    if (fullPath.equals(SQLConstant.RESERVED_TIME)) {
-      return TSDataType.INT64;
-    }
+  public List<String> getNodesList(String prefixPath, int nodeLevel) throws MetadataException {
     lock.readLock().lock();
     try {
-      return getSchemaForOnePath(fullPath).getType();
+      return mtree.getNodesList(prefixPath, nodeLevel);
     } finally {
       lock.readLock().unlock();
     }
   }
 
-  public TSDataType getSeriesType(Path path) throws PathException {
-    if (path.equals(SQLConstant.RESERVED_TIME)) {
-      return TSDataType.INT64;
-    }
-    return getSeriesType(path.getFullPath());
-  }
-
   /**
-   * function for getting series type.
+   * Get all ColumnSchemas for the storage group seriesPath.
+   *
+   * @param storageGroup storage group name
    */
-  public TSDataType getSeriesType(MNode node, String fullPath) throws PathException {
-
+  public List<MeasurementSchema> getStorageGroupSchema(String storageGroup)
+      throws MetadataException {
     lock.readLock().lock();
     try {
-      return getSchemaForOnePath(node, fullPath).getType();
+      return mtree.getStorageGroupSchema(storageGroup);
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * function for getting series type with check.
+   * Get storage group name by path
+   *
+   * e.g., root.sg1 is a storage group and path = root.sg1.d1, return root.sg1
+   *
+   * @return storage group in the given path
    */
-  TSDataType getSeriesTypeWithCheck(MNode node, String fullPath) throws PathException {
-
+  public String getStorageGroupName(String path) throws MetadataException {
     lock.readLock().lock();
     try {
-      return getSchemaForOnePathWithCheck(node, fullPath).getType();
+      return mtree.getStorageGroupName(path);
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * unction for getting series type with check.
+   * Get all storage group names
    */
-  TSDataType getSeriesTypeWithCheck(String fullPath) throws PathException {
-
+  public List<String> getAllStorageGroupNames() {
     lock.readLock().lock();
     try {
-      return getSchemaForOnePathWithCheck(fullPath).getType();
+      return mtree.getAllStorageGroupNames();
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * Get all device type in current Metadata Tree.
-   *
-   * @return a HashMap contains all distinct device type separated by device Type
+   * Get all storage group MNodes
    */
-  // future feature
-  @SuppressWarnings("unused")
-  public Map<String, List<MeasurementSchema>> getSchemaForAllType() throws PathException {
-
+  public List<StorageGroupMNode> getAllStorageGroupNodes() {
     lock.readLock().lock();
     try {
-      return mgraph.getSchemaForAllType();
+      return mtree.getAllStorageGroupNodes();
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * Get the full Metadata info.
+   * Return all paths for given path if the path is abstract. Or return the path itself. Regular
+   * expression in this method is formed by the amalgamation of seriesPath and the character '*'.
    *
-   * @return A {@code Metadata} instance which stores all metadata info
+   * @param prefixPath can be a prefix or a full path. if the wildcard is not at the tail, then each
+   * wildcard can only match one level, otherwise it can match to the tail.
    */
-  public Metadata getMetadata() throws PathException {
-
+  public List<String> getAllTimeseriesName(String prefixPath) throws MetadataException {
     lock.readLock().lock();
     try {
-      return mgraph.getMetadata();
+      return mtree.getAllTimeseriesName(prefixPath);
+    } catch (MetadataException e) {
+      throw new MetadataException(e);
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * Get the full devices info.
+   * Get all timeseries paths under the given path.
    *
-   * @return A list instance which stores all device names
+   * @param path can be root, root.*  root.*.*.a etc.. if the wildcard is not at the tail, then each
+   * wildcard can only match one level, otherwise it can match to the tail.
+   * @return for each storage group, return a List [name, sg name, data type, encoding, compressor]
    */
-  public List<String> getAllDevices() throws PathException {
-    
+  public List<String[]> getAllTimeseriesSchema(String path) throws MetadataException {
     lock.readLock().lock();
     try {
-      return mgraph.getAllDevices();
+      return mtree.getAllTimeseriesSchema(path);
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * Get devices info with given prefixPath.
+   * Get child node path in the next level of the given path.
    *
-   * @return A HashSet instance which stores devices names with given prefixPath.
+   * e.g., MTree has [root.sg1.d1.s1, root.sg1.d1.s2, root.sg1.d2.s1] given path = root.sg1, return
+   * [root.sg1.d1, root.sg1.d2]
+   *
+   * @return All child nodes' seriesPath(s) of given seriesPath.
    */
-  public List<String> getDevices(String prefixPath) throws PathException {
-
+  public Set<String> getChildNodePathInNextLevel(String path) throws MetadataException {
     lock.readLock().lock();
     try {
-      return mgraph.getDevices(prefixPath);
+      return mtree.getChildNodePathInNextLevel(path);
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * Get all nodes from the given level
+   * Check whether the path exists.
    *
-   * @return A List instance which stores all node at given level
+   * @param path a full path or a prefix path
    */
-  public List<String> getNodesList(String prefixPath, int nodeLevel) throws SQLException {
-
+  public boolean isPathExist(String path) {
     lock.readLock().lock();
     try {
-      return mgraph.getNodesList(prefixPath, nodeLevel);
+      return mtree.isPathExist(path);
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * @param path A seriesPath represented one Delta object
-   * @return a list contains all column schema
-   * @deprecated Get all MeasurementSchemas for given delta object type.
+   * Get node by path
    */
-  @Deprecated
-  public List<MeasurementSchema> getSchemaForOneType(String path) throws PathException {
+  MNode getNodeByPath(String path) throws MetadataException {
     lock.readLock().lock();
     try {
-      return mgraph.getSchemaForOneType(path);
+      return mtree.getNodeByPath(path);
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * Get all MeasurementSchemas for the storage group seriesPath.
+   * Get storage group node by path. If storage group is not set, StorageGroupNotSetException will
+   * be thrown
    */
-  public List<MeasurementSchema> getSchemaForStorageGroup(String path) {
+  public StorageGroupMNode getStorageGroupNode(String path) throws MetadataException {
     lock.readLock().lock();
     try {
-      return mgraph.getSchemaInOneStorageGroup(path);
+      return mtree.getStorageGroupNode(path);
     } finally {
       lock.readLock().unlock();
     }
   }
 
   /**
-   * function for getting schema map for one file node.
+   * get device node, if the storage group is not set, create it when autoCreateSchema is true
+   *
+   * @param path path
    */
-  private Map<String, MeasurementSchema> getStorageGroupSchemaMap(String path) {
-
+  public MNode getDeviceNodeWithAutoCreateStorageGroup(String path, boolean autoCreateSchema,
+      int sgLevel) throws MetadataException {
     lock.readLock().lock();
+    MNode node = null;
+    boolean shouldSetStorageGroup = false;
     try {
-      return mgraph.getSchemaMapForOneFileNode(path);
+      node = mNodeCache.get(path);
+    } catch (CacheException e) {
+      if (!autoCreateSchema) {
+        throw new PathNotExistException(path);
+      } else {
+        shouldSetStorageGroup = e.getCause() instanceof StorageGroupNotSetException;
+      }
     } finally {
       lock.readLock().unlock();
+      if (autoCreateSchema) {
+        if (shouldSetStorageGroup) {
+          String storageGroupName = MetaUtils.getStorageGroupNameByLevel(path, sgLevel);
+          setStorageGroup(storageGroupName);
+        }
+        node = mtree.getDeviceNodeWithAutoCreating(path);
+      }
     }
+    return node;
   }
 
-  /**
-   * function for getting num schema map for one file node.
-   */
-  private Map<String, Integer> getStorageGroupNumSchemaMap(String path) {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getNumSchemaMapForOneFileNode(path);
-    } finally {
-      lock.readLock().unlock();
-    }
+  public MNode getDeviceNodeWithAutoCreateStorageGroup(String path) throws MetadataException {
+    return getDeviceNodeWithAutoCreateStorageGroup(path, config.isAutoCreateSchemaEnabled(),
+        config.getDefaultStorageGroupLevel());
   }
 
   /**
-   * Calculate the count of storage-group nodes included in given seriesPath.
-   *
-   * @return The total count of storage-group nodes.
+   * Get metadata in string
    */
-  // future feature
-  @SuppressWarnings("unused")
-  public int getFileCountForOneType(String path) throws PathException {
-
+  public String getMetadataInString() {
     lock.readLock().lock();
     try {
-      return mgraph.getFileCountForOneType(path);
+      return TIME_SERIES_TREE_HEADER + mtree.toString();
     } finally {
       lock.readLock().unlock();
     }
   }
 
-  /**
-   * Get the file name for given seriesPath Notice: This method could be called if and only if the
-   * seriesPath includes one node whose {@code isStorageGroup} is true.
-   *
-   * @return A String represented the file name
-   */
-  public String getStorageGroupNameByPath(String path) throws StorageGroupException {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getStorageGroupNameByPath(path);
-    } catch (StorageGroupException e) {
-      throw new StorageGroupException(e.getMessage());
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting file name by path. TODO: return value unused
-   */
-  private String getStorageGroupNameByPath(MNode node, String path) throws StorageGroupException {
-    lock.readLock().lock();
-    try {
-      return mgraph.getStorageGroupNameByPath(node, path);
-    } catch (StorageGroupException e) {
-      throw new StorageGroupException(e.getMessage());
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for checking storage group name by path.
-   */
-  boolean checkStorageGroupByPath(String path) {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.checkStorageGroupByPath(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * Get the names of all storage groups.
-   *
-   * @return A list which stores all storage group names.
-   */
-  public List<String> getAllStorageGroupNames() {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getAllStorageGroupNames();
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting all storage groups' MNodes
-   */
-  public List<MNode> getAllStorageGroups() {
-    lock.readLock().lock();
-    try {
-      return mgraph.getAllStorageGroupNodes();
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * Get all storage group names for given seriesPath
-   *
-   * @return List of String represented all storage group names
-   */
-  List<String> getAllStorageGroupNamesByPath(String path) throws MetadataException {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getAllStorageGroupNamesByPath(path);
-    } catch (PathException e) {
-      throw new MetadataException(e);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * return a HashMap contains all the paths separated by storage group name.
-   */
-  Map<String, List<String>> getAllPathGroupByStorageGroup(String path)
-      throws MetadataException {
-    lock.readLock().lock();
-    try {
-      return mgraph.getAllPathGroupByStorageGroup(path);
-    } catch (PathException e) {
-      throw new MetadataException(e);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * Return all paths for given seriesPath if the seriesPath is abstract. Or return the seriesPath
-   * itself.
-   */
-  public List<String> getPaths(String path) throws MetadataException {
-
-    lock.readLock().lock();
-    try {
-      List<String> res = new ArrayList<>();
-      Map<String, List<String>> pathsGroupBySG = getAllPathGroupByStorageGroup(path);
-      for (List<String> ps : pathsGroupBySG.values()) {
-        res.addAll(ps);
-      }
-      return res;
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting all timeseries paths under the given seriesPath.
-   */
-  public List<List<String>> getShowTimeseriesPath(String path) throws PathException {
-    lock.readLock().lock();
-    try {
-      return mgraph.getShowTimeseriesPath(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting leaf node path in the next level of given seriesPath.
-   */
-  List<String> getLeafNodePathInNextLevel(String path) throws PathException {
-    lock.readLock().lock();
-    try {
-      return mgraph.getLeafNodePathInNextLevel(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting leaf node path in the next level of given seriesPath.
-   */
-  public Set<String> getChildNodePathInNextLevel(String path) throws PathException {
-    lock.readLock().lock();
-    try {
-      return mgraph.getChildNodePathInNextLevel(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * Check whether the seriesPath given exists.
-   */
-  public boolean pathExist(String path) {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.pathExist(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for checking whether the path exists.
-   */
-  boolean pathExist(MNode node, String path) {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.pathExist(node, path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting node by path.
-   */
-  MNode getNodeByPath(String path) throws PathException {
-    lock.readLock().lock();
-    try {
-      return mgraph.getNodeByPath(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting node by path from cache.
-   */
-  public MNode getNodeByPathFromCache(String path) throws CacheException, PathException {
-    IoTDBConfig conf = IoTDBDescriptor.getInstance().getConfig();
-    return getNodeByPathFromCache(path, conf.isAutoCreateSchemaEnabled(),
-        conf.getDefaultStorageGroupLevel());
-  }
-
-    /**
-     * function for getting node by deviceId from cache.
-     */
-  public MNode getNodeByPathFromCache(String deviceID, boolean autoCreateSchema, int sgLevel) throws CacheException, PathException {
-    lock.readLock().lock();
-    MNode node = null;
-    boolean createSchema = false;
-    boolean setStorageGroup = false;
-    try {
-      node = mNodeCache.get(deviceID);
-    } catch (CacheException e) {
-      if (!autoCreateSchema) {
-        throw e;
-      } else {
-        createSchema = true;
-        setStorageGroup = e.getCause() instanceof StorageGroupException;
-      }
-    } finally {
-      lock.readLock().unlock();
-      if (createSchema) {
-        if (setStorageGroup) {
-          try {
-            String storageGroupName = getStorageGroupNameByAutoLevel(deviceID, sgLevel);
-            setStorageGroupToMTree(storageGroupName);
-          } catch (MetadataException | PathException e1) {
-            throw new CacheException(e1);
-          }
-        }
-        node = addDeviceIdToMTree(deviceID);
-      }
-    }
-    return node;
-  }
-
-  /**
-   * function for getting node by path with check.
-   */
-  public MNode getNodeByPathWithCheck(String path) throws PathException, StorageGroupException {
-    lock.readLock().lock();
-    try {
-      return mgraph.getNodeByPathWithCheck(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * Get MeasurementSchema for given seriesPath. Notice: Path must be a complete Path from root to
-   * leaf node.
-   */
-  private MeasurementSchema getSchemaForOnePath(String path) throws PathException {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getSchemaForOnePath(path);
-    } finally {
-      lock.readLock().unlock();
-    }
+  @TestOnly
+  public void setMaxSeriesNumberAmongStorageGroup(long maxSeriesNumberAmongStorageGroup) {
+    this.maxSeriesNumberAmongStorageGroup = maxSeriesNumberAmongStorageGroup;
   }
 
-  /**
-   * function for getting schema for one path.
-   */
-  private MeasurementSchema getSchemaForOnePath(MNode node, String path) throws PathException {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getSchemaForOnePath(node, path);
-    } finally {
-      lock.readLock().unlock();
-    }
+  public long getMaximalSeriesNumberAmongStorageGroups() {
+    return maxSeriesNumberAmongStorageGroup;
   }
 
-  /**
-   * function for getting schema for one path with check.
-   */
-  private MeasurementSchema getSchemaForOnePathWithCheck(MNode node, String path)
-      throws PathException {
+  private static class MManagerHolder {
 
-    lock.readLock().lock();
-    try {
-      return mgraph.getSchemaForOnePathWithCheck(node, path);
-    } finally {
-      lock.readLock().unlock();
+    private MManagerHolder() {
+      //allowed to do nothing
     }
-  }
-
-  /**
-   * function for getting schema for one path with check.
-   */
-  private MeasurementSchema getSchemaForOnePathWithCheck(String path) throws PathException {
 
-    lock.readLock().lock();
-    try {
-      return mgraph.getSchemaForOnePathWithCheck(path);
-    } finally {
-      lock.readLock().unlock();
-    }
+    private static final MManager INSTANCE = new MManager();
   }
 
-  /**
-   * Check whether given seriesPath contains a MNode whose {@code MNode.isStorageGroup} is true.
-   */
-  public boolean checkFileLevel(List<Path> path) throws StorageGroupException {
-
-    lock.readLock().lock();
+  public void setTTL(String storageGroup, long dataTTL) throws MetadataException, IOException {
+    lock.writeLock().lock();
     try {
-      for (Path p : path) {
-        getStorageGroupNameByPath(p.getFullPath());
+      getStorageGroupNode(storageGroup).setDataTTL(dataTTL);
+      if (writeToLog) {
+        BufferedWriter writer = getLogWriter();
+        writer
+            .write(String.format("%s,%s,%s", MetadataOperationType.SET_TTL, storageGroup, dataTTL));
+        writer.newLine();
+        writer.flush();
       }
-      return true;
     } finally {
-      lock.readLock().unlock();
+      lock.writeLock().unlock();
     }
   }
 
   /**
-   * function for checking file level.
+   * Check whether the given path contains a storage group
    */
-  boolean checkFileLevel(MNode node, List<Path> path) throws StorageGroupException {
-
+  boolean checkStorageGroupByPath(String path) {
     lock.readLock().lock();
     try {
-      for (Path p : path) {
-        getStorageGroupNameByPath(node, p.getFullPath());
-      }
-      return true;
+      return mtree.checkStorageGroupByPath(path);
     } finally {
       lock.readLock().unlock();
     }
   }
 
-  /**
-   * function for checking file level.
-   */
-  boolean checkFileLevel(String path) throws StorageGroupException {
-
-    lock.readLock().lock();
-    try {
-      getStorageGroupNameByPath(path);
-      return true;
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
 
   /**
-   * function for checking file level with check.
-   */
-  boolean checkFileLevelWithCheck(MNode node, String path) throws StorageGroupException {
-    lock.readLock().lock();
-    try {
-      getStorageGroupNameByPath(node, path);
-      return true;
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting metadata in string.
+   * Get all storage groups under the given path
+   *
+   * @return List of String represented all storage group names
+   * @apiNote :for cluster
    */
-  public String getMetadataInString() {
+  List<String> getStorageGroupByPath(String path) throws MetadataException {
     lock.readLock().lock();
     try {
-      return TIME_SERIES_TREE_HEADER + mgraph.toString();
+      return mtree.getStorageGroupByPath(path);
+    } catch (MetadataException e) {
+      throw new MetadataException(e);
     } finally {
       lock.readLock().unlock();
     }
   }
-
-  public int getSeriesNumber(String storageGroup) {
-    return seriesNumberInStorageGroups.getOrDefault(storageGroup, 0);
-  }
-
-  /**
-   * function for getting storage group name when creating schema automatically is enable
-   */
-  String getStorageGroupNameByAutoLevel(String fullPath, int level)
-      throws PathException {
-    String[] nodeNames = MetaUtils.getNodeNames(fullPath, DOUB_SEPARATOR);
-    StringBuilder storageGroupName = new StringBuilder(nodeNames[0]);
-    if (nodeNames.length < level || !storageGroupName.toString().equals(ROOT_NAME)) {
-      throw new MTreePathException("Timeseries", fullPath);
-    }
-    for (int i = 1; i < level; i++) {
-      storageGroupName.append(IoTDBConstant.PATH_SEPARATOR).append(nodeNames[i]);
-    }
-    return storageGroupName.toString();
-  }
-
-  /**
-   * Check whether {@code seriesPath} exists and whether {@code seriesPath} has been set storage
-   * group.
-   *
-   * @return {@link PathCheckRet}
-   */
-  PathCheckRet checkPathStorageGroupAndGetDataType(String path) throws PathException {
-    try {
-      return checkAndGetDataTypeCache.get(path);
-    } catch (CacheException e) {
-      throw new MTreePathException(e.getMessage());
-    }
-  }
-
-  private PathCheckRet loadPathToCache(String path) throws CacheException {
-    try {
-      if (!pathExist(path)) {
-        return new PathCheckRet(false, null);
-      }
-      List<Path> p = new ArrayList<>();
-      p.add(new Path(path));
-      if (!checkFileLevel(p)) {
-        return new PathCheckRet(false, null);
-      }
-      return new PathCheckRet(true, getSeriesType(path));
-    } catch (PathException | StorageGroupException e) {
-      throw new CacheException(e);
-    }
-  }
-
-  /**
-   * Only for test
-   */
-  public void setMaxSeriesNumberAmongStorageGroup(long maxSeriesNumberAmongStorageGroup) {
-    this.maxSeriesNumberAmongStorageGroup = maxSeriesNumberAmongStorageGroup;
-  }
-
-  public long getMaximalSeriesNumberAmongStorageGroups() {
-    return maxSeriesNumberAmongStorageGroup;
-  }
-
-  private static class MManagerHolder {
-
-    private MManagerHolder() {
-      //allowed to do nothing
-    }
-
-    private static final MManager INSTANCE = new MManager();
-  }
-
-  public static class PathCheckRet {
-
-    private boolean successfully;
-    private TSDataType dataType;
-
-    PathCheckRet(boolean successfully, TSDataType dataType) {
-      this.successfully = successfully;
-      this.dataType = dataType;
-    }
-
-    public boolean isSuccessfully() {
-      return successfully;
-    }
-
-    public TSDataType getDataType() {
-      return dataType;
-    }
-  }
-
-  public void setTTL(String storageGroup, long dataTTL) throws PathException, IOException {
-    lock.writeLock().lock();
-    try {
-      MNode sgNode = getNodeByPath(storageGroup);
-      if (!sgNode.isStorageGroup()) {
-        throw new NotStorageGroupException(storageGroup);
-      }
-      sgNode.setDataTTL(dataTTL);
-      if (writeToLog) {
-        BufferedWriter writer = getLogWriter();
-        writer
-            .write(String.format("%s,%s,%s", MetadataOperationType.SET_TTL, storageGroup, dataTTL));
-        writer.newLine();
-        writer.flush();
-      }
-    } finally {
-      lock.writeLock().unlock();
-    }
-  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MNode.java b/server/src/main/java/org/apache/iotdb/db/metadata/MNode.java
deleted file mode 100644
index 86103bf..0000000
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MNode.java
+++ /dev/null
@@ -1,241 +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.metadata;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.apache.iotdb.db.conf.IoTDBConstant;
-import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
-import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
-import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
-
-/**
- * This class is the implementation of Metadata Node where "MNode" is the shorthand of "Metadata
- * Node". One MNode instance represents one node in the Metadata Tree
- */
-public class MNode implements Serializable {
-
-  private static final long serialVersionUID = -770028375899514063L;
-
-  // The name of the MNode
-  private String name;
-  // Whether current node is a leaf in the Metadata Tree
-  private boolean isLeaf;
-  // Whether current node is Storage group in the Metadata Tree
-  private boolean isStorageGroup;
-  // Map for the schema in this storage group
-  private Map<String, MeasurementSchema> schemaMap;
-  private Map<String, Integer> numSchemaMap;
-  // Corresponding data file name for current node
-  private String dataFileName;
-  // Column's Schema for one timeseries represented by current node if current
-  // node is one leaf
-  private MeasurementSchema schema;
-  private MNode parent;
-  private Map<String, MNode> children;
-
-  private String fullPath;
-
-  /**
-   * when the data in a storage group is older than dataTTL, it is considered invalid and will
-   * be eventually removed.
-   * only set at storage group level.
-   */
-  private long dataTTL = Long.MAX_VALUE;
-
-  /**
-   * Constructor of MNode.
-   */
-  public MNode(String name, MNode parent, boolean isLeaf) {
-    this.setName(name);
-    this.parent = parent;
-    this.isLeaf = isLeaf;
-    this.isStorageGroup = false;
-    if (!isLeaf) {
-      children = new LinkedHashMap<>();
-    }
-  }
-
-  public MNode(String name, MNode parent, TSDataType dataType, TSEncoding encoding,
-      CompressionType type) {
-    this(name, parent, true);
-    this.schema = new MeasurementSchema(name, dataType, encoding, type);
-  }
-
-  public boolean isStorageGroup() {
-    return isStorageGroup;
-  }
-
-  /**
-   * function for setting storage group.
-   */
-  public void setStorageGroup(boolean b) {
-    this.isStorageGroup = b;
-    if (b) {
-      schemaMap = new HashMap<>();
-      numSchemaMap = new HashMap<>();
-    } else {
-      numSchemaMap = null;
-      schemaMap = null;
-    }
-  }
-
-  public Map<String, MeasurementSchema> getSchemaMap() {
-    return schemaMap;
-  }
-
-  public Map<String, Integer> getNumSchemaMap() {
-    return numSchemaMap;
-  }
-
-  public boolean isLeaf() {
-    return isLeaf;
-  }
-
-  public void setLeaf(boolean isLeaf) {
-    this.isLeaf = isLeaf;
-  }
-
-  /**
-   * function for checking whether the mnode has child mnode.
-   */
-  public boolean hasChildren() {
-    if (!isLeaf) {
-      return true;
-    }
-    return false;
-  }
-
-  /**
-   * function for checking whether mnode's children contain the given key.
-   */
-  public boolean hasChild(String key) {
-    if (!isLeaf) {
-      return this.children.containsKey(key);
-    }
-    return false;
-  }
-
-  /**
-   * function for adding the given key to the given child mnode.
-   */
-  public void addChild(String key, MNode child) {
-    if (!isLeaf) {
-      this.children.put(key, child);
-    }
-  }
-
-  public void deleteChild(String key) {
-    children.remove(key);
-  }
-
-  /**
-   * function for getting the child mnode under the given key.
-   */
-  public MNode getChild(String key) {
-    if (!isLeaf) {
-      return children.get(key);
-    }
-    return null;
-  }
-
-  /**
-   * function for getting the count of all leaves whose ancestor is current node.
-   */
-  public int getLeafCount() {
-    if (isLeaf) {
-      return 1;
-    } else {
-      int leafCount = 0;
-      for (MNode child : this.children.values()) {
-        leafCount += child.getLeafCount();
-      }
-      return leafCount;
-    }
-  }
-
-  public String getDataFileName() {
-    return dataFileName;
-  }
-
-  public void setDataFileName(String dataFileName) {
-    this.dataFileName = dataFileName;
-  }
-
-  @Override
-  public String toString() {
-    return this.getName();
-  }
-
-  public MeasurementSchema getSchema() {
-    return schema;
-  }
-
-  public void setSchema(MeasurementSchema schema) {
-    this.schema = schema;
-  }
-
-  public MNode getParent() {
-    return parent;
-  }
-
-  public void setParent(MNode parent) {
-    this.parent = parent;
-  }
-
-  public Map<String, MNode> getChildren() {
-    return children;
-  }
-
-  public void setChildren(Map<String, MNode> children) {
-    this.children = children;
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String name) {
-    this.name = name;
-  }
-
-  public long getDataTTL() {
-    return dataTTL;
-  }
-
-  public void setDataTTL(long dataTTL) {
-    this.dataTTL = dataTTL;
-  }
-
-  public String getFullPath() {
-    if (fullPath != null) {
-      return fullPath;
-    }
-    StringBuilder builder = new StringBuilder(name);
-    MNode curr = this;
-    while (curr.parent != null) {
-      curr = curr.parent;
-      builder.insert(0, IoTDBConstant.PATH_SEPARATOR).insert(0, curr.name);
-    }
-    return fullPath = builder.toString();
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java b/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
index 5a7fc26..9be1476 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MTree.java
@@ -18,26 +18,33 @@
  */
 package org.apache.iotdb.db.metadata;
 
+import static org.apache.iotdb.db.conf.IoTDBConstant.PATH_SEPARATOR;
+import static org.apache.iotdb.db.conf.IoTDBConstant.PATH_WILDCARD;
+
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.serializer.SerializerFeature;
 import java.io.Serializable;
-import java.sql.SQLException;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.Stack;
+import org.apache.iotdb.db.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.exception.path.MTreePathException;
-import org.apache.iotdb.db.exception.path.PathException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupNotSetException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupPathException;
-import org.apache.iotdb.db.qp.constant.SQLConstant;
+import org.apache.iotdb.db.exception.metadata.IllegalPathException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
+import org.apache.iotdb.db.exception.metadata.PathAlreadyExistException;
+import org.apache.iotdb.db.exception.metadata.PathNotExistException;
+import org.apache.iotdb.db.exception.metadata.StorageGroupAlreadySetException;
+import org.apache.iotdb.db.exception.metadata.StorageGroupNotSetException;
+import org.apache.iotdb.db.metadata.mnode.InternalMNode;
+import org.apache.iotdb.db.metadata.mnode.LeafMNode;
+import org.apache.iotdb.db.metadata.mnode.MNode;
+import org.apache.iotdb.db.metadata.mnode.StorageGroupMNode;
 import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
@@ -50,388 +57,236 @@ import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
 public class MTree implements Serializable {
 
   private static final long serialVersionUID = -4200394435237291964L;
-  private static final String PATH_SEPARATOR = "\\.";
-  private static final String NO_CHILD_ERROR = "Node [%s] doesn't have child named: [%s]";
-  private static final String NOT_LEAF_NODE = "is NOT the leaf node";
   private MNode root;
 
-  MTree(String rootName) {
-    this.root = new MNode(rootName, null, false);
+  MTree() {
+    this.root = new InternalMNode(null, IoTDBConstant.PATH_ROOT);
   }
 
   /**
-   * function for adding timeseries.It should check whether seriesPath exists.
-   */
-  void addTimeseriesPath(String timeseriesPath, TSDataType dataType, TSEncoding encoding,
-      CompressionType compressor, Map<String, String> props) throws PathException {
-    String[] nodeNames = MetaUtils.getNodeNames(timeseriesPath, PATH_SEPARATOR);
-    if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) {
-      throw new MTreePathException("Timeseries", timeseriesPath);
-    }
-    MNode cur = findLeafParent(nodeNames);
-    String levelPath = cur.getDataFileName();
-
-    MNode leaf = new MNode(nodeNames[nodeNames.length - 1], cur, dataType, encoding, compressor);
-    if (props != null && !props.isEmpty()) {
-      leaf.getSchema().setProps(props);
-    }
-    leaf.setDataFileName(levelPath);
-    if (cur.isLeaf()) {
-      throw new MTreePathException(timeseriesPath, "can't be created",
-          String.format("node [%s] is left node", cur.getName()));
-    }
-    cur.addChild(nodeNames[nodeNames.length - 1], leaf);
-  }
-
-  /**
-   * function for adding deviceId
-   */
-  MNode addDeviceId(String deviceId) throws PathException {
-    String[] nodeNames = MetaUtils.getNodeNames(deviceId, PATH_SEPARATOR);
-    if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) {
-      throw new MTreePathException("Timeseries", deviceId);
-    }
-    MNode cur = getRoot();
-    for (int i = 1; i < nodeNames.length; i++) {
-      if (!cur.hasChild(nodeNames[i])) {
-        cur.addChild(nodeNames[i], new MNode(nodeNames[i], cur, false));
-      }
-      cur = cur.getChild(nodeNames[i]);
+   * Create a timeseries with a full path from root to leaf node Before creating a timeseries, the
+   * storage group should be set first, throw exception otherwise
+   *
+   * @param path timeseries path
+   * @param dataType data type
+   * @param encoding encoding
+   * @param compressor compressor
+   * @param props props
+   */
+  void createTimeseries(String path, TSDataType dataType, TSEncoding encoding,
+      CompressionType compressor, Map<String, String> props) throws MetadataException {
+    String[] nodeNames = MetaUtils.getNodeNames(path);
+    if (nodeNames.length <= 2 || !nodeNames[0].equals(root.getName())) {
+      throw new IllegalPathException(path);
     }
-    return cur;
-  }
-
-  private MNode findLeafParent(String[] nodeNames) throws PathException {
     MNode cur = root;
-    String levelPath = null;
-    int i = 1;
-    while (i < nodeNames.length - 1) {
+    boolean hasSetStorageGroup = false;
+    // e.g, path = root.sg.d1.s1,  create internal node root -> sg -> d1
+    for (int i = 1; i < nodeNames.length - 1; i++) {
       String nodeName = nodeNames[i];
-      if (cur.isStorageGroup()) {
-        levelPath = cur.getDataFileName();
+      if (cur instanceof StorageGroupMNode) {
+        hasSetStorageGroup = true;
       }
       if (!cur.hasChild(nodeName)) {
-        if (cur.isLeaf()) {
-          throw new MTreePathException(String.join(",", nodeNames), "can't be created",
-              String.format("node [%s] is left node", cur.getName()));
+        if (cur instanceof LeafMNode) {
+          throw new PathAlreadyExistException(cur.getFullPath());
+        } else if (!hasSetStorageGroup) {
+          throw new StorageGroupNotSetException("Storage group should be created first");
         }
-        cur.addChild(nodeName, new MNode(nodeName, cur, false));
+        cur.addChild(new InternalMNode(cur, nodeName));
       }
-      cur.setDataFileName(levelPath);
       cur = cur.getChild(nodeName);
-      if (levelPath == null) {
-        levelPath = cur.getDataFileName();
-      }
-      i++;
     }
-    cur.setDataFileName(levelPath);
-    return cur;
+    MNode leaf = new LeafMNode(cur, nodeNames[nodeNames.length - 1], dataType, encoding,
+        compressor, props);
+    cur.addChild(leaf);
   }
 
-
   /**
-   * function for checking whether the given path exists.
+   * Add an interval path to MTree. This is only used for automatically creating schema
    *
-   * @param path -seriesPath not necessarily the whole seriesPath (possibly a prefix of a sequence)
+   * e.g., get root.sg.d1, get or create all internal nodes and return the node of d1
    */
-  boolean isPathExist(String path) {
-    String[] nodeNames = nodeNames = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+  MNode getDeviceNodeWithAutoCreating(String deviceId) throws MetadataException {
+    String[] nodeNames = MetaUtils.getNodeNames(deviceId);
+    if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) {
+      throw new IllegalPathException(deviceId);
+    }
     MNode cur = root;
-    int i = 0;
-    while (i < nodeNames.length - 1) {
-      String nodeName = nodeNames[i];
-      if (cur.getName().equals(nodeName)) {
-        i++;
-        nodeName = nodeNames[i];
-        if (cur.hasChild(nodeName)) {
-          cur = cur.getChild(nodeName);
-        } else {
-          return false;
-        }
-      } else {
-        return false;
+    for (int i = 1; i < nodeNames.length; i++) {
+      if (!cur.hasChild(nodeNames[i])) {
+        cur.addChild(new InternalMNode(cur, nodeNames[i]));
       }
+      cur = cur.getChild(nodeNames[i]);
     }
-    return cur.getName().equals(nodeNames[i]);
+    return cur;
   }
 
   /**
-   * function for checking whether the given path exists under the given mNode.
+   * Check whether the given path exists.
+   *
+   * @param path a full path or a prefix path
    */
-  boolean isPathExist(MNode node, String path) {
-    String[] nodeNames = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodeNames.length < 1) {
-      return true;
-    }
-    if (!node.hasChild(nodeNames[0])) {
+  boolean isPathExist(String path) {
+    String[] nodeNames = MetaUtils.getNodeNames(path);
+    MNode cur = root;
+    if (!nodeNames[0].equals(root.getName())) {
       return false;
     }
-    MNode cur = node.getChild(nodeNames[0]);
-
-    int i = 0;
-    while (i < nodeNames.length - 1) {
-      String nodeName = nodeNames[i];
-      if (cur.getName().equals(nodeName)) {
-        i++;
-        nodeName = nodeNames[i];
-        if (cur.hasChild(nodeName)) {
-          cur = cur.getChild(nodeName);
-        } else {
-          return false;
-        }
+    for (int i = 1; i < nodeNames.length; i++) {
+      String childName = nodeNames[i];
+      if (cur.hasChild(childName)) {
+        cur = cur.getChild(childName);
       } else {
         return false;
       }
     }
-    return cur.getName().equals(nodeNames[i]);
+    return true;
   }
 
   /**
-   * make sure check seriesPath before setting storage group.
+   * Set storage group. Make sure check seriesPath before setting storage group
+   *
+   * @param path path
    */
-  public void setStorageGroup(String path) throws StorageGroupException {
-    String[] nodeNames = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+  void setStorageGroup(String path) throws MetadataException {
+    String[] nodeNames = MetaUtils.getNodeNames(path);
     MNode cur = root;
     if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) {
-      throw new StorageGroupException(
-          String.format("The storage group can't be set to [%s] node", path));
+      throw new IllegalPathException(path);
     }
     int i = 1;
+    // e.g., path = root.a.b.sg, create internal nodes for a, b
     while (i < nodeNames.length - 1) {
       MNode temp = cur.getChild(nodeNames[i]);
       if (temp == null) {
-        // add one child node
-        cur.addChild(nodeNames[i], new MNode(nodeNames[i], cur, false));
-      } else if (temp.isStorageGroup()) {
-        // before set storage group should check the seriesPath exist or not
-        // throw exception
-        throw new StorageGroupException(
-            String.format("The prefix of [%s] has been set to the storage group.", path));
+        cur.addChild(new InternalMNode(cur, nodeNames[i]));
+      } else if (temp instanceof StorageGroupMNode) {
+        // before set storage group, check whether the exists or not
+        throw new StorageGroupAlreadySetException(temp.getFullPath());
       }
       cur = cur.getChild(nodeNames[i]);
       i++;
     }
-    MNode temp = cur.getChild(nodeNames[i]);
-    if (temp == null) {
-      cur.addChild(nodeNames[i], new MNode(nodeNames[i], cur, false));
+    if (cur.hasChild(nodeNames[i])) {
+      // node b has child sg
+      throw new StorageGroupAlreadySetException(path);
     } else {
-      throw new StorageGroupException(String
-          .format("The seriesPath of [%s] already exist, it can't be set to the storage group",
-              path));
+      StorageGroupMNode storageGroupMNode = new StorageGroupMNode(cur, nodeNames[i], path,
+          IoTDBDescriptor.getInstance().getConfig().getDefaultTTL(), new HashMap<>());
+      cur.addChild(storageGroupMNode);
     }
-    cur = cur.getChild(nodeNames[i]);
-    cur.setDataTTL(IoTDBDescriptor.getInstance().getConfig().getDefaultTTL());
-    cur.setStorageGroup(true);
-
-    setStorageGroup(path, cur);
   }
 
-  void deleteStorageGroup(String path) throws PathException {
-    MNode cur = getNode(path);
-    if (!cur.isStorageGroup()) {
-      throw new MTreePathException(
-          String.format("The path [%s] is not a deletable storage group", path));
+  /**
+   * Delete a storage group
+   */
+  void deleteStorageGroup(String path) throws MetadataException {
+    MNode cur = getNodeByPath(path);
+    if (!(cur instanceof StorageGroupMNode)) {
+      throw new StorageGroupNotSetException(path);
     }
+    // Suppose current system has root.a.b.sg1, root.a.sg2, and delete root.a.b.sg1
+    // delete the storage group node sg1
     cur.getParent().deleteChild(cur.getName());
     cur = cur.getParent();
-    while (cur != null && !MetadataConstant.ROOT.equals(cur.getName())
-        && cur.getChildren().size() == 0) {
+    // delete node b while retain root.a.sg2
+    while (!IoTDBConstant.PATH_ROOT.equals(cur.getName()) && cur.getChildren().size() == 0) {
       cur.getParent().deleteChild(cur.getName());
       cur = cur.getParent();
     }
   }
 
   /**
-   * Check whether the input path is storage group or not
+   * Check whether path is storage group or not
+   *
+   * e.g., path = root.a.b.sg. if nor a and b is StorageGroupMNode and sg is a StorageGroupMNode
+   * path is a storage group
    *
-   * @param path input path
-   * @return if the whole path is a storage group, return true. Else return false
+   * @param path path
    * @apiNote :for cluster
    */
-  boolean checkStorageGroup(String path) {
-    String[] nodeNames = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    MNode cur = root;
-    if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) {
+  boolean isStorageGroup(String path) {
+    String[] nodeNames = MetaUtils.getNodeNames(path);
+    if (nodeNames.length <= 1 || !nodeNames[0].equals(IoTDBConstant.PATH_ROOT)) {
       return false;
     }
+    MNode cur = root;
     int i = 1;
     while (i < nodeNames.length - 1) {
-      MNode temp = cur.getChild(nodeNames[i]);
-      if (temp == null || temp.isStorageGroup()) {
+      cur = cur.getChild(nodeNames[i]);
+      if (cur == null || cur instanceof StorageGroupMNode) {
         return false;
       }
-      cur = cur.getChild(nodeNames[i]);
       i++;
     }
-    MNode temp = cur.getChild(nodeNames[i]);
-    return temp != null && temp.isStorageGroup();
-  }
-
-  private void setStorageGroup(String path, MNode node) {
-    node.setDataFileName(path);
-    if (node.getChildren() == null) {
-      return;
-    }
-    for (MNode child : node.getChildren().values()) {
-      setStorageGroup(path, child);
-    }
+    cur = cur.getChild(nodeNames[i]);
+    return cur instanceof StorageGroupMNode;
   }
 
   /**
-   * Delete one seriesPath from current Metadata Tree.
+   * Delete path. The path should be a full path from root to leaf node
    *
-   * @param path Format: root.node.(node)* Notice: Path must be a complete Path from root to leaf
-   * node.
+   * @param path Format: root.node(.node)+
    */
-  String deletePath(String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length == 0 || !nodes[0].equals(getRoot().getName())) {
-      throw new MTreePathException("Timeseries", path);
+  String deleteTimeseriesAndReturnEmptyStorageGroup(String path) throws MetadataException {
+    MNode curNode = getNodeByPath(path);
+    if (!(curNode instanceof LeafMNode)) {
+      throw new PathNotExistException(path);
     }
-
-    MNode cur = getRoot();
-    for (int i = 1; i < nodes.length; i++) {
-      if (!cur.hasChild(nodes[i])) {
-        throw new MTreePathException("", "is not correct",
-            String.format(NO_CHILD_ERROR, cur.getName(), nodes[i]));
-      }
-      cur = cur.getChild(nodes[i]);
-    }
-
-    // if the storage group node is deleted, the dataFileName should be
-    // return
-    String dataFileName = null;
-    if (cur.isStorageGroup()) {
-      dataFileName = cur.getDataFileName();
+    String[] nodes = MetaUtils.getNodeNames(path);
+    if (nodes.length == 0 || !IoTDBConstant.PATH_ROOT.equals(nodes[0])) {
+      throw new IllegalPathException(path);
     }
-    cur.getParent().deleteChild(cur.getName());
-    cur = cur.getParent();
-    while (cur != null && !MetadataConstant.ROOT.equals(cur.getName())
-        && cur.getChildren().size() == 0) {
-      if (cur.isStorageGroup()) {
-        dataFileName = cur.getDataFileName();
-        return dataFileName;
+    // delete the last node of path
+    curNode.getParent().deleteChild(curNode.getName());
+    curNode = curNode.getParent();
+    // delete all empty ancestors except storage group
+    while (!IoTDBConstant.PATH_ROOT.equals(curNode.getName())
+        && curNode.getChildren().size() == 0) {
+      // if current storage group has no time series, return the storage group name
+      if (curNode instanceof StorageGroupMNode) {
+        return curNode.getFullPath();
       }
-      cur.getParent().deleteChild(cur.getName());
-      cur = cur.getParent();
+      curNode.getParent().deleteChild(curNode.getName());
+      curNode = curNode.getParent();
     }
-
-    return dataFileName;
+    return null;
   }
 
   /**
-   * Get ColumnSchema for given seriesPath. Notice: Path must be a complete Path from root to leaf
-   * node.
+   * Get measurement schema for a given path. Path must be a complete Path from root to leaf node.
    */
-  MeasurementSchema getSchemaForOnePath(String path) throws PathException {
-    MNode leaf = getLeafByPath(path);
-    return leaf.getSchema();
-  }
-
-  MeasurementSchema getSchemaForOnePath(MNode node, String path) throws PathException {
-    MNode leaf = getLeafByPath(node, path);
-    return leaf.getSchema();
-  }
-
-  MeasurementSchema getSchemaForOnePathWithCheck(MNode node, String path)
-      throws PathException {
-    MNode leaf = getLeafByPathWithCheck(node, path);
-    return leaf.getSchema();
-  }
-
-  MeasurementSchema getSchemaForOnePathWithCheck(String path) throws PathException {
-    MNode leaf = getLeafByPathWithCheck(path);
-    return leaf.getSchema();
-  }
-
-  private MNode getLeafByPath(String path) throws PathException {
-    getNode(path);
-    String[] node = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    MNode cur = getRoot();
-    for (int i = 1; i < node.length; i++) {
-      cur = cur.getChild(node[i]);
-    }
-    if (!cur.isLeaf()) {
-      throw new MTreePathException(path, NOT_LEAF_NODE, "");
-    }
-    return cur;
-  }
-
-  private MNode getLeafByPath(MNode node, String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    MNode cur = node.getChild(nodes[0]);
-    for (int i = 1; i < nodes.length; i++) {
-      cur = cur.getChild(nodes[i]);
-    }
-    if (!cur.isLeaf()) {
-      throw new MTreePathException(path, NOT_LEAF_NODE, "");
-    }
-    return cur;
-  }
-
-  private MNode getLeafByPathWithCheck(MNode node, String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length < 1 || !node.hasChild(nodes[0])) {
-      throw new MTreePathException("Timeseries", path);
-    }
-
-    MNode cur = node.getChild(nodes[0]);
-    for (int i = 1; i < nodes.length; i++) {
-      if (!cur.hasChild(nodes[i])) {
-        throw new MTreePathException("", "is not correct",
-            String.format(NO_CHILD_ERROR, cur.getName(), nodes[i]));
-      }
-      cur = cur.getChild(nodes[i]);
-    }
-    if (!cur.isLeaf()) {
-      throw new MTreePathException(path, NOT_LEAF_NODE, "");
+  MeasurementSchema getSchema(String path) throws MetadataException {
+    MNode node = getNodeByPath(path);
+    if (!(node instanceof LeafMNode)) {
+      throw new PathNotExistException(path);
     }
-    return cur;
-  }
-
-  private MNode getLeafByPathWithCheck(String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length < 2 || !nodes[0].equals(getRoot().getName())) {
-      throw new MTreePathException("Timeseries", path);
-    }
-
-    MNode cur = getRoot();
-    for (int i = 1; i < nodes.length; i++) {
-      if (!cur.hasChild(nodes[i])) {
-        throw new MTreePathException("", "is not correct",
-            String.format(NO_CHILD_ERROR, cur.getName(), nodes[i]));
-      }
-      cur = cur.getChild(nodes[i]);
-    }
-    if (!cur.isLeaf()) {
-      throw new MTreePathException(path, NOT_LEAF_NODE, "");
-    }
-    return cur;
+    return node.getSchema();
   }
 
   /**
-   * function for getting node by path with file level check.
+   * Get node by path with storage group check If storage group is not set,
+   * StorageGroupNotSetException will be thrown
    */
-  MNode getNodeByPathWithStorageGroupCheck(String path)
-      throws PathException, StorageGroupException {
+  MNode getNodeByPathWithStorageGroupCheck(String path) throws MetadataException {
     boolean storageGroupChecked = false;
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length < 2 || !nodes[0].equals(getRoot().getName())) {
-      throw new MTreePathException("Timeseries", path);
+    String[] nodes = MetaUtils.getNodeNames(path);
+    if (nodes.length == 0 || !nodes[0].equals(root.getName())) {
+      throw new IllegalPathException(path);
     }
 
-    MNode cur = getRoot();
+    MNode cur = root;
     for (int i = 1; i < nodes.length; i++) {
       if (!cur.hasChild(nodes[i])) {
         if (!storageGroupChecked) {
           throw new StorageGroupNotSetException(path);
         }
-        throw new MTreePathException("", "is not correct",
-            String.format(NO_CHILD_ERROR, cur.getName(), nodes[i]));
+        throw new PathNotExistException(path);
       }
       cur = cur.getChild(nodes[i]);
 
-      if (cur.isStorageGroup()) {
+      if (cur instanceof StorageGroupMNode) {
         storageGroupChecked = true;
       }
     }
@@ -443,179 +298,110 @@ public class MTree implements Serializable {
   }
 
   /**
-   * find and return a seriesPath specified by the path
-   *
-   * @return last node in given seriesPath
+   * Get storage group node, if the give path is not a storage group, throw exception
    */
-  MNode getNode(String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length < 2 || !nodes[0].equals(getRoot().getName())) {
-      throw new MTreePathException("Timeseries", path);
-    }
-    MNode cur = getRoot();
-    for (int i = 1; i < nodes.length; i++) {
-      if (!cur.hasChild(nodes[i])) {
-        throw new MTreePathException(
-            "Path: [" + path + "] doesn't correspond to any known time series");
-      }
-      cur = cur.getChild(nodes[i]);
-    }
-    return cur;
-  }
-
-  private void checkPath(MNode node, String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length < 1) {
-      return;
-    }
-    MNode cur = node;
-    for (String node1 : nodes) {
-      if (!cur.hasChild(node1)) {
-        throw new MTreePathException("", "is not correct",
-            String.format(NO_CHILD_ERROR, cur.getName(), node1));
-      }
-      cur = cur.getChild(node1);
+  StorageGroupMNode getStorageGroupNode(String path) throws MetadataException {
+    MNode node = getNodeByPath(path);
+    if (node instanceof StorageGroupMNode) {
+      return (StorageGroupMNode) node;
+    } else {
+      throw new StorageGroupNotSetException(path);
     }
   }
 
   /**
-   * Get the storage group seriesPath from the seriesPath.
+   * Get node by the path
    *
-   * @return String storage group seriesPath
+   * @return last node in given seriesPath
    */
-  String getStorageGroupNameByPath(String path) throws StorageGroupException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    MNode cur = getRoot();
+  MNode getNodeByPath(String path) throws MetadataException {
+    String[] nodes = MetaUtils.getNodeNames(path);
+    if (nodes.length == 0 || !nodes[0].equals(root.getName())) {
+      throw new IllegalPathException(path);
+    }
+    MNode cur = root;
     for (int i = 1; i < nodes.length; i++) {
-      if (cur == null) {
-        throw new StorageGroupPathException(path);
-      } else if (cur.isStorageGroup()) {
-        return cur.getDataFileName();
-      } else {
-        cur = cur.getChild(nodes[i]);
+      if (!cur.hasChild(nodes[i])) {
+        throw new PathNotExistException(path);
       }
+      cur = cur.getChild(nodes[i]);
     }
-    if (cur.isStorageGroup()) {
-      return cur.getDataFileName();
-    }
-    throw new StorageGroupPathException(path);
+    return cur;
   }
 
   /**
-   * Get all the storage group seriesPaths for one seriesPath.
+   * Get all storage groups under the given path
    *
-   * @return List storage group seriesPath list
+   * @return storage group list
    * @apiNote :for cluster
    */
-  List<String> getAllFileNamesByPath(String pathReg) throws PathException {
-    ArrayList<String> fileNames = new ArrayList<>();
-    String[] nodes = MetaUtils.getNodeNames(pathReg, PATH_SEPARATOR);
-    if (nodes.length == 0 || !nodes[0].equals(getRoot().getName())) {
-      throw new MTreePathException("Timeseries", pathReg);
+  List<String> getStorageGroupByPath(String path) throws MetadataException {
+    List<String> storageGroups = new ArrayList<>();
+    String[] nodes = MetaUtils.getNodeNames(path);
+    if (nodes.length == 0 || !nodes[0].equals(root.getName())) {
+      throw new IllegalPathException(path);
     }
-    findFileName(getRoot(), nodes, 1, "", fileNames);
-    return fileNames;
+    findStorageGroup(root, nodes, 1, "", storageGroups);
+    return storageGroups;
   }
 
   /**
-   * Recursively find all fileName according to a specific path
+   * Recursively find all storage group according to a specific path
    *
    * @apiNote :for cluster
    */
-  private void findFileName(MNode node, String[] nodes, int idx, String parent,
-      ArrayList<String> paths) {
-    if (node.isStorageGroup()) {
-      paths.add(node.getDataFileName());
+  private void findStorageGroup(MNode node, String[] nodes, int idx, String parent,
+      List<String> storageGroupNames) {
+    if (node instanceof StorageGroupMNode) {
+      storageGroupNames.add(node.getFullPath());
       return;
     }
-    String nodeReg;
-    if (idx >= nodes.length) {
-      nodeReg = "*";
-    } else {
-      nodeReg = nodes[idx];
-    }
-
-    if (!("*").equals(nodeReg)) {
+    String nodeReg = MetaUtils.getNodeRegByIdx(idx, nodes);
+    if (!(PATH_WILDCARD).equals(nodeReg)) {
       if (node.hasChild(nodeReg)) {
-        findFileName(node.getChild(nodeReg), nodes, idx + 1, parent + node.getName() + ".", paths);
+        findStorageGroup(node.getChild(nodeReg), nodes, idx + 1,
+            parent + node.getName() + PATH_SEPARATOR, storageGroupNames);
       }
     } else {
       for (MNode child : node.getChildren().values()) {
-        findFileName(child, nodes, idx + 1, parent + node.getName() + ".", paths);
+        findStorageGroup(child, nodes, idx + 1, parent + node.getName() + PATH_SEPARATOR,
+            storageGroupNames);
       }
     }
   }
 
   /**
-   * function for getting file name by path.
-   */
-  String getStorageGroupNameByPath(MNode node, String path) throws StorageGroupException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    MNode cur = node.getChild(nodes[0]);
-    for (int i = 1; i < nodes.length; i++) {
-      if (cur == null) {
-        throw new StorageGroupPathException(path);
-      } else if (cur.isStorageGroup()) {
-        return cur.getDataFileName();
-      } else {
-        cur = cur.getChild(nodes[i]);
-      }
-    }
-    if (cur.isStorageGroup()) {
-      return cur.getDataFileName();
-    }
-    throw new StorageGroupPathException(path);
-  }
-
-  /**
-   * Check the prefix of this seriesPath is storage group seriesPath.
+   * Get all storage group names
    *
-   * @return true the prefix of this seriesPath is storage group seriesPath false the prefix of this
-   * seriesPath is not storage group seriesPath
+   * @return a list contains all distinct storage groups
    */
-  boolean checkFileNameByPath(String path) {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    MNode cur = getRoot();
-    for (int i = 1; i <= nodes.length; i++) {
-      if (cur == null) {
-        return false;
-      } else if (cur.isStorageGroup()) {
-        return true;
+  List<String> getAllStorageGroupNames() {
+    List<String> res = new ArrayList<>();
+    Deque<MNode> nodeStack = new ArrayDeque<>();
+    nodeStack.add(root);
+    while (!nodeStack.isEmpty()) {
+      MNode current = nodeStack.pop();
+      if (current instanceof StorageGroupMNode) {
+        res.add(current.getFullPath());
       } else {
-        cur = cur.getChild(nodes[i]);
+        nodeStack.addAll(current.getChildren().values());
       }
     }
-    return false;
-  }
-
-  /**
-   * Get all paths for given seriesPath regular expression Regular expression in this method is
-   * formed by the amalgamation of seriesPath and the character '*'.
-   *
-   * @return A HashMap whose Keys are separated by the storage file name.
-   */
-  HashMap<String, List<String>> getAllPath(String pathReg) throws PathException {
-    HashMap<String, List<String>> paths = new HashMap<>();
-    String[] nodes = MetaUtils.getNodeNames(pathReg, PATH_SEPARATOR);
-    if (nodes.length == 0 || !nodes[0].equals(getRoot().getName())) {
-      throw new MTreePathException("Timeseries", pathReg);
-    }
-    findPath(getRoot(), nodes, 1, "", paths);
-    return paths;
+    return res;
   }
 
   /**
-   * @return all storage groups' MNodes
+   * Get all storage group MNodes
    */
-  List<MNode> getAllStorageGroupNodes() {
-    List<MNode> ret = new ArrayList<>();
-    Stack<MNode> nodeStack = new Stack<>();
-    nodeStack.add(getRoot());
+  List<StorageGroupMNode> getAllStorageGroupNodes() {
+    List<StorageGroupMNode> ret = new ArrayList<>();
+    Deque<MNode> nodeStack = new ArrayDeque<>();
+    nodeStack.add(root);
     while (!nodeStack.isEmpty()) {
       MNode current = nodeStack.pop();
-      if (current.isStorageGroup()) {
-        ret.add(current);
-      } else if (current.hasChildren()) {
+      if (current instanceof StorageGroupMNode) {
+        ret.add((StorageGroupMNode) current);
+      } else if (current instanceof InternalMNode) {
         nodeStack.addAll(current.getChildren().values());
       }
     }
@@ -623,166 +409,153 @@ public class MTree implements Serializable {
   }
 
   /**
-   * function for getting all timeseries paths under the given seriesPath.
-   */
-  List<List<String>> getShowTimeseriesPath(String pathReg) throws PathException {
-    List<List<String>> res = new ArrayList<>();
-    String[] nodes = MetaUtils.getNodeNames(pathReg, PATH_SEPARATOR);
-    if (nodes.length == 0 || !nodes[0].equals(getRoot().getName())) {
-      throw new MTreePathException("Timeseries", pathReg);
-    }
-    findPath(getRoot(), nodes, 1, "", res);
-    return res;
-  }
-
-  /**
-   * function for getting leaf node path in the next level of the given path.
+   * Get storage group name by path
    *
-   * @return All leaf nodes' seriesPath(s) of given seriesPath.
-   */
-  List<String> getLeafNodePathInNextLevel(String path) throws PathException {
-    List<String> ret = new ArrayList<>();
-    MNode cur = getNode(path);
-    for (MNode child : cur.getChildren().values()) {
-      if (child.isLeaf()) {
-        ret.add(path + "." + child.getName());
-      }
-    }
-    return ret;
-  }
-  
-  /**
-   * function for getting child node path in the next level of the given path.
+   * e.g., root.sg1 is storage group, path is root.sg1.d1, return root.sg1
    *
-   * @return All child nodes' seriesPath(s) of given seriesPath.
+   * @return storage group in the given path
    */
-  Set<String> getChildNodePathInNextLevel(String path) throws PathException {
-    Set<String> ret = new HashSet<>();
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (!nodes[0].equals(getRoot().getName())) {
-      throw new MTreePathException("The prefix of the seriesPath [%s] is not one storage group seriesPath", path);
-
-    }
-    MNode cur = getRoot();
+  String getStorageGroupName(String path) throws MetadataException {
+    String[] nodes = MetaUtils.getNodeNames(path);
+    MNode cur = root;
     for (int i = 1; i < nodes.length; i++) {
-      if (!cur.hasChild(nodes[i])) {
-        throw new MTreePathException("Path: \"" + path + "\" doesn't correspond to any known time series");
-      }
       cur = cur.getChild(nodes[i]);
+      if (cur instanceof StorageGroupMNode) {
+        return cur.getFullPath();
+      } else if (cur == null) {
+        throw new StorageGroupNotSetException(path);
+      }
     }
-    if (!cur.hasChildren()) {
-      throw new MTreePathException("Path: \"" + path + "\" doesn't have a child node");
-    }
-    for (MNode child : cur.getChildren().values()) {
-      ret.add(path + "." + child.getName());
-    }
-    return ret;
-  }  
+    throw new StorageGroupNotSetException(path);
+  }
 
   /**
-   * function for getting all paths in list.
+   * Check whether the given path contains a storage group
    */
-  List<String> getAllPathInList(String path) throws PathException {
-    List<String> res = new ArrayList<>();
-    HashMap<String, List<String>> mapRet = getAllPath(path);
-    for (List<String> value : mapRet.values()) {
-      res.addAll(value);
+  boolean checkStorageGroupByPath(String path) {
+    String[] nodes = MetaUtils.getNodeNames(path);
+    MNode cur = root;
+    for (int i = 1; i <= nodes.length; i++) {
+      cur = cur.getChild(nodes[i]);
+      if (cur == null) {
+        return false;
+      } else if (cur instanceof StorageGroupMNode) {
+        return true;
+      }
     }
-    return res;
+    return false;
   }
 
   /**
-   * Calculate the count of storage-level nodes included in given seriesPath.
+   * Get all timeseries under the given path
    *
-   * @return The total count of storage-level nodes.
+   * @param prefixPath a prefix path or a full path, may contain '*'.
    */
-  int getFileCountForOneType(String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length != 2 || !nodes[0].equals(getRoot().getName()) || !getRoot()
-        .hasChild(nodes[1])) {
-      throw new MTreePathException("Timeseries must be " + getRoot().getName()
-          + ". X (X is one of the nodes of root's children)");
-    }
-    return getFileCountForOneNode(getRoot().getChild(nodes[1]));
-  }
-
-  private int getFileCountForOneNode(MNode node) {
-
-    if (node.isStorageGroup()) {
-      return 1;
-    }
-    int sum = 0;
-    if (!node.isLeaf()) {
-      for (MNode child : node.getChildren().values()) {
-        sum += getFileCountForOneNode(child);
-      }
+  List<String> getAllTimeseriesName(String prefixPath) throws MetadataException {
+    List<String[]> res = getAllTimeseriesSchema(prefixPath);
+    List<String> paths = new ArrayList<>();
+    for (String[] p : res) {
+      paths.add(p[0]);
     }
-    return sum;
+    return paths;
   }
 
   /**
-   * Get all device type in current Metadata Tree.
+   * Get all time series schema under the given path
    *
-   * @return a list contains all distinct device type
+   * timeseriesSchema: [name, storage group, dataType, encoding, compression]
    */
-  ArrayList<String> getAllType() {
-    ArrayList<String> res = new ArrayList<>();
-    if (getRoot() != null) {
-      res.addAll(getRoot().getChildren().keySet());
+  List<String[]> getAllTimeseriesSchema(String prefixPath) throws MetadataException {
+    List<String[]> res = new ArrayList<>();
+    String[] nodes = MetaUtils.getNodeNames(prefixPath);
+    if (nodes.length == 0 || !nodes[0].equals(root.getName())) {
+      throw new IllegalPathException(prefixPath);
     }
+    findPath(root, nodes, 1, "", res);
     return res;
   }
 
   /**
-   * Get all storage groups in current Metadata Tree.
+   * Iterate through MTree to fetch metadata info of all leaf nodes under the given seriesPath
    *
-   * @return a list contains all distinct storage groups
+   * @param timeseriesSchemaList List<timeseriesSchema>
    */
-  List<String> getAllStorageGroupList() {
-    List<String> res = new ArrayList<>();
-    MNode rootNode;
-    if ((rootNode = getRoot()) != null) {
-      findStorageGroup(rootNode, "root", res);
-    }
-    return res;
-  }
-
-  private void findStorageGroup(MNode node, String path, List<String> res) {
-    if (node.isStorageGroup()) {
-      res.add(path);
+  private void findPath(MNode node, String[] nodes, int idx, String parent,
+      List<String[]> timeseriesSchemaList) throws MetadataException {
+    if (node instanceof LeafMNode) {
+      if (nodes.length <= idx) {
+        String nodeName;
+        if (node.getName().contains(TsFileConstant.PATH_SEPARATOR)) {
+          nodeName = "\"" + node + "\"";
+        } else {
+          nodeName = node.getName();
+        }
+        String nodePath = parent + nodeName;
+        String[] tsRow = new String[5];
+        tsRow[0] = nodePath;
+        MeasurementSchema measurementSchema = node.getSchema();
+        tsRow[1] = getStorageGroupName(nodePath);
+        tsRow[2] = measurementSchema.getType().toString();
+        tsRow[3] = measurementSchema.getEncodingType().toString();
+        tsRow[4] = measurementSchema.getCompressor().toString();
+        timeseriesSchemaList.add(tsRow);
+      }
       return;
     }
-    for (MNode childNode : node.getChildren().values()) {
-      findStorageGroup(childNode, path + "." + childNode.toString(), res);
+    String nodeReg = MetaUtils.getNodeRegByIdx(idx, nodes);
+    if (!(PATH_WILDCARD).equals(nodeReg)) {
+      if (node.hasChild(nodeReg)) {
+        findPath(node.getChild(nodeReg), nodes, idx + 1, parent + node.getName() + PATH_SEPARATOR,
+            timeseriesSchemaList);
+      }
+    } else {
+      for (MNode child : node.getChildren().values()) {
+        findPath(child, nodes, idx + 1, parent + node.getName() + PATH_SEPARATOR,
+            timeseriesSchemaList);
+      }
     }
   }
 
   /**
-   * Get all devices in current Metadata Tree.
+   * Get child node path in the next level of the given path.
+   *
+   * e.g., MTree has [root.sg1.d1.s1, root.sg1.d1.s2, root.sg1.d2.s1] given path = root.sg1, return
+   * [root.sg1.d1, root.sg1.d2]
    *
-   * @return a list contains all distinct device names
+   * @return All child nodes' seriesPath(s) of given seriesPath.
    */
-  List<String> getAllDevices() throws PathException {
-    return getDevices(SQLConstant.ROOT);
+  Set<String> getChildNodePathInNextLevel(String path) throws MetadataException {
+    MNode node = getNodeByPath(path);
+
+    if (node instanceof LeafMNode) {
+      return new HashSet<>();
+    }
+
+    Set<String> childPaths = new HashSet<>();
+    for (MNode child : node.getChildren().values()) {
+      childPaths.add(path + PATH_SEPARATOR + child.getName());
+    }
+    return childPaths;
   }
 
   /**
-   * Get all devices in current Metadata Tree with prefixPath.
+   * Get all devices under give path
    *
    * @return a list contains all distinct devices names
    */
-  List<String> getDevices(String prefixPath) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(prefixPath, PATH_SEPARATOR);
-    if (nodes.length == 0 || !nodes[0].equals(getRoot().getName())) {
-      throw new MTreePathException("PrefixPath", prefixPath);
+  List<String> getDevices(String prefixPath) throws MetadataException {
+    String[] nodes = MetaUtils.getNodeNames(prefixPath);
+    if (nodes.length == 0 || !nodes[0].equals(root.getName())) {
+      throw new IllegalPathException(prefixPath);
     }
     List<String> devices = new ArrayList<>();
-    findDevices(getRoot(), nodes, 1, "", devices);
+    findDevices(root, nodes, 1, "", devices);
     return devices;
   }
 
   /**
    * Traverse the MTree to match all devices with prefix path.
+   *
    * @param node the current traversing node
    * @param nodes split the prefix path with '.'
    * @param idx the current index of array nodes
@@ -790,56 +563,47 @@ public class MTree implements Serializable {
    * @param res store all matched device names
    */
   private void findDevices(MNode node, String[] nodes, int idx, String parent, List<String> res) {
-    String nodeReg;
-    if (idx >= nodes.length) {
-      nodeReg = "*";
-    } else {
-      nodeReg = nodes[idx];
-    }
-    if (!("*").equals(nodeReg)) {
+    String nodeReg = MetaUtils.getNodeRegByIdx(idx, nodes);
+    if (!(PATH_WILDCARD).equals(nodeReg)) {
       if (node.hasChild(nodeReg)) {
-        if(node.getChild(nodeReg).isLeaf()){
+        if (node.getChild(nodeReg) instanceof LeafMNode) {
           res.add(parent + node.getName());
-        } else{
-          findDevices(node.getChild(nodeReg), nodes, idx + 1, parent + node.getName() + ".", res);
+        } else {
+          findDevices(node.getChild(nodeReg), nodes, idx + 1,
+              parent + node.getName() + PATH_SEPARATOR, res);
         }
       }
     } else {
       boolean deviceAdded = false;
       for (MNode child : node.getChildren().values()) {
-        if(child.isLeaf() && !deviceAdded){
+        if (child instanceof LeafMNode && !deviceAdded) {
           res.add(parent + node.getName());
           deviceAdded = true;
-        } else if (!child.isLeaf()){
-          findDevices(child, nodes, idx + 1, parent + node.getName() + ".", res);
+        } else if (!(child instanceof LeafMNode)) {
+          findDevices(child, nodes, idx + 1, parent + node.getName() + PATH_SEPARATOR, res);
         }
       }
     }
   }
 
   /**
-   * Get all nodes at the given level in current Metadata Tree.
-   *
-   * @return a list contains all nodes at the given level
+   * Get all paths from root to the given level
    */
-  List<String> getNodesList(String schemaPattern, int nodeLevel) throws SQLException {
+  List<String> getNodesList(String path, int nodeLevel) throws MetadataException {
+    String[] nodes = MetaUtils.getNodeNames(path);
+    if (!nodes[0].equals(root.getName())) {
+      throw new IllegalPathException(path);
+    }
     List<String> res = new ArrayList<>();
-    String[] nodes = MetaUtils.getNodeNames(schemaPattern, PATH_SEPARATOR);
-    MNode node;
-    if ((node = getRoot()) != null) {
-      if (nodes[0].equals("root")) {
-        for (int i = 1; i < nodes.length; i++) {
-          if (node.getChild(nodes[i]) != null) {
-            node = node.getChild(nodes[i]);
-          } else {
-            throw new SQLException(nodes[i - 1] + " does not have the child node " + nodes[i]);
-          }
-        }
-        findNodes(node, schemaPattern, res, nodeLevel - (nodes.length - 1));
+    MNode node = root;
+    for (int i = 1; i < nodes.length; i++) {
+      if (node.getChild(nodes[i]) != null) {
+        node = node.getChild(nodes[i]);
       } else {
-        throw new SQLException("Incorrect root node " + nodes[0] + " selected");
+        throw new MetadataException(nodes[i - 1] + " does not have the child node " + nodes[i]);
       }
     }
+    findNodes(node, path, res, nodeLevel - (nodes.length - 1));
     return res;
   }
 
@@ -851,227 +615,64 @@ public class MTree implements Serializable {
       res.add(path);
       return;
     }
-    if (node.hasChildren()) {
+    if (node instanceof InternalMNode) {
       for (MNode child : node.getChildren().values()) {
-        findNodes(child, path + "." + child.toString(), res, targetLevel - 1);
+        findNodes(child, path + PATH_SEPARATOR + child.toString(), res, targetLevel - 1);
       }
     }
   }
 
   /**
-   * Get all delta objects for given type.
-   *
-   * @param type device Type
-   * @return a list contains all delta objects for given type
-   */
-  ArrayList<String> getDeviceForOneType(String type) throws PathException {
-    String path = getRoot().getName() + "." + type;
-    getNode(path);
-    HashMap<String, Integer> deviceMap = new HashMap<>();
-    MNode typeNode = getRoot().getChild(type);
-    putDeviceToMap(getRoot().getName(), typeNode, deviceMap);
-    return new ArrayList<>(deviceMap.keySet());
-  }
-
-  private void putDeviceToMap(String path, MNode node, HashMap<String, Integer> deviceMap) {
-    if (node.isLeaf()) {
-      deviceMap.put(path, 1);
-    } else {
-      for (String child : node.getChildren().keySet()) {
-        String newPath = path + "." + node.getName();
-        putDeviceToMap(newPath, node.getChildren().get(child), deviceMap);
-      }
-    }
-  }
-
-  /**
-   * Get all ColumnSchemas for given delta object type.
-   *
-   * @param path A seriesPath represented one Delta object
-   * @return a list contains all column schema
-   */
-  ArrayList<MeasurementSchema> getSchemaForOneType(String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length != 2 || !nodes[0].equals(getRoot().getName()) || !getRoot()
-        .hasChild(nodes[1])) {
-      throw new MTreePathException("Timeseries must be " + getRoot().getName()
-          + ". X (X is one of the nodes of root's children)");
-    }
-    HashMap<String, MeasurementSchema> leafMap = new HashMap<>();
-    putLeafToLeafMap(getRoot().getChild(nodes[1]), leafMap);
-    return new ArrayList<>(leafMap.values());
-  }
-
-  /**
-   * Get all ColumnSchemas for the storage group seriesPath.
+   * Get all ColumnSchemas for the storage group path.
    *
    * @return ArrayList<ColumnSchema> The list of the schema
    */
-  ArrayList<MeasurementSchema> getSchemaForOneStorageGroup(String path) {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    HashMap<String, MeasurementSchema> leafMap = new HashMap<>();
-    MNode cur = getRoot();
-    for (int i = 1; i < nodes.length; i++) {
-      cur = cur.getChild(nodes[i]);
-    }
-    // cur is the storage group node
-    putLeafToLeafMap(cur, leafMap);
-    return new ArrayList<>(leafMap.values());
-  }
-
-  /**
-   * function for getting schema map for one storage group.
-   */
-  Map<String, MeasurementSchema> getSchemaMapForOneStorageGroup(String path) {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    MNode cur = getRoot();
-    for (int i = 1; i < nodes.length; i++) {
-      cur = cur.getChild(nodes[i]);
-    }
-    return cur.getSchemaMap();
+  List<MeasurementSchema> getStorageGroupSchema(String storageGroup) throws MetadataException {
+    StorageGroupMNode storageGroupMNode = getStorageGroupNode(storageGroup);
+    return new ArrayList<>(storageGroupMNode.getSchemaMap().values());
   }
 
   /**
-   * function for getting num schema map for one file node.
-   */
-  Map<String, Integer> getNumSchemaMapForOneFileNode(String path) {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    MNode cur = getRoot();
-    for (int i = 1; i < nodes.length; i++) {
-      cur = cur.getChild(nodes[i]);
-    }
-    return cur.getNumSchemaMap();
-  }
-
-  private void putLeafToLeafMap(MNode node, HashMap<String, MeasurementSchema> leafMap) {
-    if (node.isLeaf()) {
-      if (!leafMap.containsKey(node.getName())) {
-        leafMap.put(node.getName(), node.getSchema());
-      }
-      return;
-    }
-    for (MNode child : node.getChildren().values()) {
-      putLeafToLeafMap(child, leafMap);
-    }
-  }
-
-  private void findPath(MNode node, String[] nodes, int idx, String parent,
-      HashMap<String, List<String>> paths) {
-    if (node.isLeaf()) {
-      if (nodes.length <= idx) {
-        String fileName = node.getDataFileName();
-        String nodeName;
-        if (node.getName().contains(TsFileConstant.PATH_SEPARATOR)) {
-          nodeName = "\"" + node + "\"";
-        } else {
-          nodeName = "" + node;
-        }
-        String nodePath = parent + nodeName;
-        putAPath(paths, fileName, nodePath);
-      }
-      return;
-    }
-    String nodeReg;
-    if (idx >= nodes.length) {
-      nodeReg = "*";
-    } else {
-      nodeReg = nodes[idx];
-    }
-
-    if (!("*").equals(nodeReg)) {
-      if (node.hasChild(nodeReg)) {
-        findPath(node.getChild(nodeReg), nodes, idx + 1, parent + node.getName() + ".", paths);
-      }
-    } else {
-      for (MNode child : node.getChildren().values()) {
-        findPath(child, nodes, idx + 1, parent + node.getName() + ".", paths);
-      }
-    }
-  }
-
-  /*
-   * Iterate through MTree to fetch metadata info of all leaf nodes under the given seriesPath
+   * Get schema map for the storage group
+   *
+   * measurement -> measurementSchema
    */
-  private void findPath(MNode node, String[] nodes, int idx, String parent,
-      List<List<String>> res) {
-    if (node.isLeaf()) {
-      if (nodes.length <= idx) {
-        String nodePath = parent + node;
-        List<String> tsRow = new ArrayList<>(5);// get [name,storage group,resultDataType,encoding]
-        tsRow.add(nodePath);
-        MeasurementSchema measurementSchema = node.getSchema();
-        tsRow.add(node.getDataFileName());
-        tsRow.add(measurementSchema.getType().toString());
-        tsRow.add(measurementSchema.getEncodingType().toString());
-        tsRow.add(measurementSchema.getCompressor().toString());
-        res.add(tsRow);
-      }
-      return;
-    }
-    String nodeReg;
-    if (idx >= nodes.length) {
-      nodeReg = "*";
-    } else {
-      nodeReg = nodes[idx];
-    }
-
-    if (!("*").equals(nodeReg)) {
-      if (node.hasChild(nodeReg)) {
-        findPath(node.getChild(nodeReg), nodes, idx + 1, parent + node.getName() + ".", res);
-      }
-    } else {
-      for (MNode child : node.getChildren().values()) {
-        findPath(child, nodes, idx + 1, parent + node.getName() + ".", res);
-      }
-    }
-  }
-
-  private void putAPath(HashMap<String, List<String>> paths, String fileName,
-      String nodePath) {
-    if (paths.containsKey(fileName)) {
-      paths.get(fileName).add(nodePath);
-    } else {
-      List<String> pathList = new ArrayList<>();
-      pathList.add(nodePath);
-      paths.put(fileName, pathList);
-    }
+  Map<String, MeasurementSchema> getStorageGroupSchemaMap(String storageGroup)
+      throws MetadataException {
+    StorageGroupMNode storageGroupMNode = getStorageGroupNode(storageGroup);
+    return storageGroupMNode.getSchemaMap();
   }
 
   @Override
   public String toString() {
-    return jsonToString(toJson());
+    JSONObject jsonObject = new JSONObject();
+    jsonObject.put(root.getName(), mNodeToJSON(root, null));
+    return jsonToString(jsonObject);
   }
 
   private static String jsonToString(JSONObject jsonObject) {
     return JSON.toJSONString(jsonObject, SerializerFeature.PrettyFormat);
   }
 
-  private JSONObject toJson() {
-    JSONObject jsonObject = new JSONObject();
-    jsonObject.put(getRoot().getName(), mNodeToJSON(getRoot()));
-    return jsonObject;
-  }
-
-  private JSONObject mNodeToJSON(MNode node) {
+  private JSONObject mNodeToJSON(MNode node, String storageGroupName) {
     JSONObject jsonObject = new JSONObject();
-    if (!node.isLeaf() && node.getChildren().size() > 0) {
+    if (node.getChildren().size() > 0) {
+      if (node instanceof StorageGroupMNode) {
+        storageGroupName = node.getFullPath();
+      }
       for (MNode child : node.getChildren().values()) {
-        jsonObject.put(child.getName(), mNodeToJSON(child));
+        jsonObject.put(child.getName(), mNodeToJSON(child, storageGroupName));
       }
-    } else if (node.isLeaf()) {
+    } else if (node instanceof LeafMNode) {
       jsonObject.put("DataType", node.getSchema().getType());
       jsonObject.put("Encoding", node.getSchema().getEncodingType());
       jsonObject.put("Compressor", node.getSchema().getCompressor());
       jsonObject.put("args", node.getSchema().getProps().toString());
-      jsonObject.put("StorageGroup", node.getDataFileName());
+      jsonObject.put("StorageGroup", storageGroupName);
     }
     return jsonObject;
   }
 
-  public MNode getRoot() {
-    return root;
-  }
-
   /**
    * combine multiple metadata in string format
    */
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MetaUtils.java b/server/src/main/java/org/apache/iotdb/db/metadata/MetaUtils.java
index 6899c2f..c42ab21 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MetaUtils.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MetaUtils.java
@@ -18,27 +18,61 @@
  */
 package org.apache.iotdb.db.metadata;
 
-public class MetaUtils {
-  public static String[] getNodeNames(String path, String separator) {
+import static org.apache.iotdb.db.conf.IoTDBConstant.PATH_WILDCARD;
+
+import org.apache.iotdb.db.conf.IoTDBConstant;
+import org.apache.iotdb.db.exception.metadata.IllegalPathException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
+
+class MetaUtils {
+
+  public static final String PATH_SEPARATOR = "\\.";
+
+  private MetaUtils() {
+
+  }
+
+  public static String[] getNodeNames(String path) {
     String[] nodeNames;
-    path = path.trim();
     if (path.contains("\"") || path.contains("\'")) {
-      String[] deviceAndMeasurement;
-      if (path.contains("\"")) {
-        deviceAndMeasurement = path.split("\"");
-      } else {
-        deviceAndMeasurement = path.split("\'");
-      }
-      String device = deviceAndMeasurement[0];
-      String measurement = deviceAndMeasurement[1];
-      String[] deviceNodeName = device.split(separator);
+      // e.g., root.sg.d1."s1.int"  ->  root.sg.d1, s1.int
+      String[] measurementDeviceNode = path.trim().replace("\'", "\"").split("\"");
+      // s1.int
+      String measurement = measurementDeviceNode[1];
+      // root.sg.d1 -> root, sg, d1
+      String[] deviceNodeName = measurementDeviceNode[0].split(PATH_SEPARATOR);
       int nodeNumber = deviceNodeName.length + 1;
       nodeNames = new String[nodeNumber];
       System.arraycopy(deviceNodeName, 0, nodeNames, 0, nodeNumber - 1);
+      // nodeNames = [root, sg, d1, s1.int]
       nodeNames[nodeNumber - 1] = measurement;
     } else {
-      nodeNames = path.split(separator);
+      nodeNames = path.split(PATH_SEPARATOR);
     }
     return nodeNames;
   }
+
+  static String getNodeRegByIdx(int idx, String[] nodes) {
+    return idx >= nodes.length ? PATH_WILDCARD : nodes[idx];
+  }
+
+  /**
+   * Get storage group name when creating schema automatically is enable
+   *
+   * e.g., path = root.a.b.c and level = 2, return root.a
+   *
+   * @param path path
+   * @param level level
+   */
+  public static String getStorageGroupNameByLevel(String path, int level) throws MetadataException {
+    String[] nodeNames = MetaUtils.getNodeNames(path);
+    if (nodeNames.length < level || !nodeNames[0].equals(IoTDBConstant.PATH_ROOT)) {
+      throw new IllegalPathException(path);
+    }
+    StringBuilder storageGroupName = new StringBuilder(nodeNames[0]);
+    for (int i = 1; i < level; i++) {
+      storageGroupName.append(IoTDBConstant.PATH_SEPARATOR).append(nodeNames[i]);
+    }
+    return storageGroupName.toString();
+  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MetadataOperationType.java b/server/src/main/java/org/apache/iotdb/db/metadata/MetadataOperationType.java
index dce3523..72d34f4 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MetadataOperationType.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MetadataOperationType.java
@@ -24,16 +24,9 @@ public class MetadataOperationType {
     //allowed to do nothing
   }
 
-  public static final String ADD_PATH_TO_MTREE = "0";
-  public static final String DELETE_PATH_FROM_MTREE = "1";
-  public static final String SET_STORAGE_GROUP_TO_MTREE = "2";
-  public static final String ADD_A_PTREE = "3";
-  public static final String ADD_A_PATH_TO_PTREE = "4";
-  public static final String DELETE_PATH_FROM_PTREE = "5";
-  public static final String LINK_MNODE_TO_PTREE = "6";
-  public static final String UNLINK_MNODE_FROM_PTREE = "7";
-  public static final String ADD_INDEX_TO_PATH = "8";
-  public static final String DELETE_INDEX_FROM_PATH = "9";
+  public static final String CREATE_TIMESERIES = "0";
+  public static final String DELETE_TIMESERIES = "1";
+  public static final String SET_STORAGE_GROUP = "2";
   public static final String SET_TTL = "10";
-  public static final String DELETE_STORAGE_GROUP_FROM_MTREE = "11";
+  public static final String DELETE_STORAGE_GROUP = "11";
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/PNode.java b/server/src/main/java/org/apache/iotdb/db/metadata/PNode.java
deleted file mode 100644
index adfc3b8..0000000
--- a/server/src/main/java/org/apache/iotdb/db/metadata/PNode.java
+++ /dev/null
@@ -1,127 +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.metadata;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import org.apache.iotdb.db.exception.path.PathException;
-
-/**
- * PNode is the shorthand for "Property Node", which make up The {@code PTree}
- */
-public class PNode implements Serializable {
-
-  private static final long serialVersionUID = -7166236304286006338L;
-  private String name;
-  private PNode parent;
-  private HashMap<String, PNode> children;
-  private boolean isLeaf;
-
-  /**
-   * This HashMap contains all the {@code MNode} this {@code PNode} is responsible for
-   */
-  private LinkedHashMap<String, Integer> linkedMTreePathMap;
-
-  public PNode(String name, PNode parent, boolean isLeaf) {
-    this.name = name;
-    this.parent = parent;
-    this.isLeaf = isLeaf;
-    if (!isLeaf) {
-      setChildren(new HashMap<>());
-    } else {
-      linkedMTreePathMap = new LinkedHashMap<>();
-    }
-  }
-
-  public void linkMPath(String mTreePath) throws PathException {
-    if (!isLeaf) {
-      throw new PathException("Current PNode is NOT leaf node");
-    }
-    if (!linkedMTreePathMap.containsKey(mTreePath)) {
-      linkedMTreePathMap.put(mTreePath, 1);
-    }
-  }
-
-  public void unlinkMPath(String mTreePath) throws PathException {
-    if (!isLeaf) {
-      throw new PathException("Current PNode is NOT leaf node");
-    }
-    if (!linkedMTreePathMap.containsKey(mTreePath)) {
-      return;
-    }
-    linkedMTreePathMap.remove(mTreePath);
-  }
-
-  public boolean hasChild(String key) {
-    return getChildren().containsKey(key);
-  }
-
-  public PNode getChild(String key) {
-    return getChildren().get(key);
-  }
-
-  public void addChild(String name, PNode node) {
-    this.getChildren().put(name, node);
-  }
-
-  public void deleteChild(String name) {
-    this.getChildren().remove(name);
-  }
-
-  public boolean isLeaf() {
-    return isLeaf;
-  }
-
-  public void setLeaf(boolean isLeaf) {
-    this.isLeaf = isLeaf;
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String name) {
-    this.name = name;
-  }
-
-  public PNode getParent() {
-    return parent;
-  }
-
-  public void setParent(PNode parent) {
-    this.parent = parent;
-  }
-
-  public HashMap<String, PNode> getChildren() {
-    return children;
-  }
-
-  public void setChildren(HashMap<String, PNode> children) {
-    this.children = children;
-  }
-
-  public HashMap<String, Integer> getLinkedMTreePathMap() {
-    return linkedMTreePathMap;
-  }
-
-  public void setLinkedMTreePathMap(LinkedHashMap<String, Integer> linkedMTreePathMap) {
-    this.linkedMTreePathMap = linkedMTreePathMap;
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/PTree.java b/server/src/main/java/org/apache/iotdb/db/metadata/PTree.java
deleted file mode 100644
index a7f45f5..0000000
--- a/server/src/main/java/org/apache/iotdb/db/metadata/PTree.java
+++ /dev/null
@@ -1,244 +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.metadata;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import org.apache.iotdb.db.exception.path.PTreePathException;
-import org.apache.iotdb.db.exception.path.PathException;
-
-/**
- * "PTree" is the shorthand for "Property Tree". One {@code PTree} consists several {@code PNode}
- */
-public class PTree implements Serializable {
-
-  private static final long serialVersionUID = 2642766399323283900L;
-  private static final String PTREE_NOT_EXIST = "PTree seriesPath not exist. ";
-  private PNode root;
-  private MTree mTree;
-  private String name;
-  private String space = "    ";
-
-  PTree(String name, MTree mTree) {
-    this.setRoot(new PNode(name, null, false));
-    this.setName(name);
-    this.setmTree(mTree);
-  }
-
-  /**
-   * Add a seriesPath to current PTree
-   *
-   * @return The count of new added {@code PNode} TODO: unused
-   */
-  int addPath(String path) throws PathException {
-    int addCount = 0;
-    if (getRoot() == null) {
-      throw new PTreePathException("Root Node is null, Please initialize root first");
-    }
-    String[] nodes = MetaUtils.getNodeNames(path, "\\.");
-    if (nodes.length <= 1 || !nodes[0].equals(getRoot().getName())) {
-      throw new PTreePathException("Input seriesPath not exist. Path: " + path);
-    }
-
-    PNode cur = getRoot();
-    int i;
-    for (i = 1; i < nodes.length - 1; i++) {
-      if (!cur.hasChild(nodes[i])) {
-        cur.addChild(nodes[i], new PNode(nodes[i], cur, false));
-        addCount++;
-      }
-      cur = cur.getChild(nodes[i]);
-    }
-    if (cur.hasChild(nodes[i])) {
-      throw new PTreePathException("Path already exists. Path: " + path);
-    } else {
-      PNode node = new PNode(nodes[i], cur, true);
-      cur.addChild(node.getName(), node);
-      addCount++;
-    }
-    return addCount;
-  }
-
-  /**
-   * Remove a seriesPath from current PTree
-   */
-  void deletePath(String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, "\\.");
-    if (nodes.length == 0 || !nodes[0].equals(getRoot().getName())) {
-      throw new PTreePathException("Path not correct. Path:" + path);
-    }
-    PNode cur = getRoot();
-    for (int i = 1; i < nodes.length; i++) {
-      if (!cur.hasChild(nodes[i])) {
-        throw new PTreePathException(
-            "Path not correct. Node[" + cur.getName() + "] doesn't have child named:" + nodes[i]);
-      }
-      cur = cur.getChild(nodes[i]);
-    }
-    cur.getParent().deleteChild(cur.getName());
-  }
-
-  /**
-   * Link a {@code MNode} to a {@code PNode} in current PTree
-   */
-  void linkMNode(String pTreePath, String mTreePath) throws PathException {
-    List<String> paths = mTree.getAllPathInList(mTreePath);
-    String[] nodes = MetaUtils.getNodeNames(pTreePath, "\\.");
-    PNode leaf = getLeaf(getRoot(), nodes, 0);
-    for (String p : paths) {
-      leaf.linkMPath(p);
-    }
-  }
-
-  /**
-   * Unlink a {@code MNode} from a {@code PNode} in current PTree
-   */
-  void unlinkMNode(String pTreePath, String mTreePath) throws PathException {
-    List<String> paths = mTree.getAllPathInList(mTreePath);
-    String[] nodes = MetaUtils.getNodeNames(pTreePath, "\\.");
-    PNode leaf = getLeaf(getRoot(), nodes, 0);
-    for (String p : paths) {
-      leaf.unlinkMPath(p);
-    }
-  }
-
-  private PNode getLeaf(PNode node, String[] nodes, int idx) throws PathException {
-    if (idx >= nodes.length) {
-      throw new PTreePathException(PTREE_NOT_EXIST);
-    }
-    if (node.isLeaf()) {
-      if (idx != nodes.length - 1 || !nodes[idx].equals(node.getName())) {
-        throw new PTreePathException(PTREE_NOT_EXIST);
-      }
-      return node;
-    } else {
-      if (idx >= nodes.length - 1 || !node.hasChild(nodes[idx + 1])) {
-        throw new PTreePathException(PTREE_NOT_EXIST);
-      }
-      return getLeaf(node.getChild(nodes[idx + 1]), nodes, idx + 1);
-    }
-  }
-
-  /**
-   * @param path a seriesPath in current {@code PTree} Get all linked seriesPath in MTree according
-   * to the given seriesPath in PTree
-   * @return Paths will be separated by the {@code MNode.dataFileName} in the HashMap
-   */
-  HashMap<String, List<String>> getAllLinkedPath(String path) throws PathException {
-    String[] nodes = MetaUtils.getNodeNames(path, "\\.");
-    PNode leaf = getLeaf(getRoot(), nodes, 0);
-    HashMap<String, List<String>> res = new HashMap<>();
-
-    for (String MPath : leaf.getLinkedMTreePathMap().keySet()) {
-      HashMap<String, List<String>> tr = getmTree().getAllPath(MPath);
-      mergePathRes(res, tr);
-    }
-    return res;
-  }
-
-  private void mergePathRes(HashMap<String, List<String>> res, HashMap<String, List<String>> tr) {
-    for (String key : tr.keySet()) {
-      if (!res.containsKey(key)) {
-        res.put(key, new ArrayList<>());
-      }
-      for (String p : tr.get(key)) {
-        if (!res.get(key).contains(p)) {
-          res.get(key).add(p);
-        }
-      }
-    }
-  }
-
-  @Override
-  public String toString() {
-    return pNodeToString(getRoot(), 0);
-  }
-
-  private String pNodeToString(PNode node, int tab) {
-    StringBuilder s = new StringBuilder();
-    for (int i = 0; i < tab; i++) {
-      s.append(space);
-    }
-    s.append(node.getName());
-    if (!node.isLeaf() && node.getChildren().size() > 0) {
-      s.append(":{\n");
-      int first = 0;
-      for (PNode child : node.getChildren().values()) {
-        if (first == 0) {
-          first = 1;
-        } else {
-          s.append(",\n");
-        }
-        s.append(pNodeToString(child, tab + 1));
-      }
-      s.append("\n");
-      for (int i = 0; i < tab; i++) {
-        s.append(space);
-      }
-      s.append("}");
-    } else if (node.isLeaf()) {
-      s.append(":{\n");
-      String[] linkedPaths = node.getLinkedMTreePathMap().values().stream().map(
-          Object::toString).toArray(String[]::new);
-      for (int i = 0; i < linkedPaths.length; i++) {
-        if (i != linkedPaths.length - 1) {
-          s.append(getTabs(tab + 1)).append(linkedPaths[i]).append(",\n");
-        } else {
-          s.append(getTabs(tab + 1)).append(linkedPaths[i]).append("\n");
-        }
-      }
-      s.append(getTabs(tab)).append("}");
-    }
-    return s.toString();
-  }
-
-  private String getTabs(int count) {
-    StringBuilder sb = new StringBuilder();
-    for (int i = 0; i < count; i++) {
-      sb.append(space);
-    }
-    return sb.toString();
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String name) {
-    this.name = name;
-  }
-
-  private MTree getmTree() {
-    return mTree;
-  }
-
-  private void setmTree(MTree mTree) {
-    this.mTree = mTree;
-  }
-
-  public PNode getRoot() {
-    return root;
-  }
-
-  public void setRoot(PNode root) {
-    this.root = root;
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/InternalMNode.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/InternalMNode.java
new file mode 100644
index 0000000..18d56df
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/InternalMNode.java
@@ -0,0 +1,74 @@
+/*
+ * 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.metadata.mnode;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+
+public class InternalMNode extends MNode {
+
+  private static final long serialVersionUID = 7999036474525817732L;
+
+  private Map<String, MNode> children;
+
+  public InternalMNode(MNode parent, String name) {
+    super(parent, name);
+    this.children = new LinkedHashMap<>();
+  }
+
+  @Override
+  public boolean hasChild(String name) {
+    return this.children.containsKey(name);
+  }
+
+  @Override
+  public void addChild(MNode child) {
+    this.children.put(child.getName(), child);
+  }
+
+  @Override
+  public void deleteChild(String name) {
+    children.remove(name);
+  }
+
+  @Override
+  public MNode getChild(String name) {
+    return children.get(name);
+  }
+
+  @Override
+  public int getLeafCount() {
+    int leafCount = 0;
+    for (MNode child : this.children.values()) {
+      leafCount += child.getLeafCount();
+    }
+    return leafCount;
+  }
+
+  @Override
+  public MeasurementSchema getSchema() {
+    return null;
+  }
+
+  @Override
+  public Map<String, MNode> getChildren() {
+    return children;
+  }
+}
\ No newline at end of file
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/LeafMNode.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/LeafMNode.java
new file mode 100644
index 0000000..e74c41c
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/LeafMNode.java
@@ -0,0 +1,77 @@
+/*
+ * 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.metadata.mnode;
+
+import java.util.Collections;
+import java.util.Map;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
+import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+
+public class LeafMNode extends MNode {
+
+  private static final long serialVersionUID = -1199657856921206435L;
+
+  /**
+   * measurement's Schema for one timeseries represented by current leaf node
+   */
+  private MeasurementSchema schema;
+
+  public LeafMNode(MNode parent, String name, TSDataType dataType, TSEncoding encoding,
+      CompressionType type, Map<String, String> props) {
+    super(parent, name);
+    this.schema = new MeasurementSchema(name, dataType, encoding, type, props);
+  }
+
+  @Override
+  public boolean hasChild(String name) {
+    return false;
+  }
+
+  @Override
+  public void addChild(MNode child) {
+    // Do nothing
+  }
+
+  @Override
+  public void deleteChild(String name) {
+    // Do nothing
+  }
+
+  @Override
+  public MNode getChild(String name) {
+    return null;
+  }
+
+  @Override
+  public int getLeafCount() {
+    return 1;
+  }
+
+  @Override
+  public Map<String, MNode> getChildren() {
+    return Collections.emptyMap();
+  }
+
+  @Override
+  public MeasurementSchema getSchema() {
+    return schema;
+  }
+}
\ No newline at end of file
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/MNode.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/MNode.java
new file mode 100644
index 0000000..3ac7310
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/MNode.java
@@ -0,0 +1,116 @@
+/*
+ * 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.metadata.mnode;
+
+import java.io.Serializable;
+import java.util.Map;
+import org.apache.iotdb.db.conf.IoTDBConstant;
+import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+
+/**
+ * This class is the implementation of Metadata Node. One MNode instance represents one node in the
+ * Metadata Tree
+ */
+public abstract class MNode implements Serializable {
+
+  private static final long serialVersionUID = -770028375899514063L;
+
+  /**
+   * Name of the MNode
+   */
+  private String name;
+
+  private MNode parent;
+
+  /**
+   * from root to this node, only be set when used once
+   */
+  protected String fullPath;
+
+  /**
+   * Constructor of MNode.
+   */
+  public MNode(MNode parent, String name) {
+    this.parent = parent;
+    this.name = name;
+  }
+
+  /**
+   * check whether the MNode has a child with the name
+   */
+  public abstract boolean hasChild(String name);
+
+  /**
+   * add the given child
+   */
+  public abstract void addChild(MNode child);
+
+  /**
+   * delete a child
+   */
+  public abstract void deleteChild(String name);
+
+  /**
+   * get the child with the name
+   */
+  public abstract MNode getChild(String name);
+
+  /**
+   * get the count of all leaves whose ancestor is current node
+   */
+  public abstract int getLeafCount();
+
+  /**
+   * get full path
+   */
+  public String getFullPath() {
+    if (fullPath != null) {
+      return fullPath;
+    }
+    StringBuilder builder = new StringBuilder(name);
+    MNode curr = this;
+    while (curr.getParent() != null) {
+      curr = curr.getParent();
+      builder.insert(0, IoTDBConstant.PATH_SEPARATOR).insert(0, curr.name);
+    }
+    fullPath = builder.toString();
+    return fullPath;
+  }
+
+  @Override
+  public String toString() {
+    return this.getName();
+  }
+
+  public abstract MeasurementSchema getSchema();
+
+  public MNode getParent() {
+    return parent;
+  }
+
+  public abstract Map<String, MNode> getChildren();
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+}
\ No newline at end of file
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupMNode.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupMNode.java
new file mode 100644
index 0000000..960a52a
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/StorageGroupMNode.java
@@ -0,0 +1,59 @@
+/*
+ * 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.metadata.mnode;
+
+import java.util.Map;
+import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+
+public class StorageGroupMNode extends InternalMNode {
+
+  private static final long serialVersionUID = 7999036474525817732L;
+
+  /**
+   * when the data file in a storage group is older than dataTTL, it is considered invalid and will
+   * be eventually deleted.
+   */
+  private long dataTTL;
+
+  /**
+   * Map for the schema in this storage group
+   */
+  private Map<String, MeasurementSchema> schemaMap;
+
+  public StorageGroupMNode(MNode parent, String name, String fullPath, long dataTTL,
+      Map<String, MeasurementSchema> schemaMap) {
+    super(parent, name);
+    this.dataTTL = dataTTL;
+    this.schemaMap = schemaMap;
+    this.fullPath = fullPath;
+  }
+
+  public long getDataTTL() {
+    return dataTTL;
+  }
+
+  public void setDataTTL(long dataTTL) {
+    this.dataTTL = dataTTL;
+  }
+
+  public Map<String, MeasurementSchema> getSchemaMap() {
+    return schemaMap;
+  }
+
+}
\ No newline at end of file
diff --git a/server/src/main/java/org/apache/iotdb/db/monitor/StatMonitor.java b/server/src/main/java/org/apache/iotdb/db/monitor/StatMonitor.java
index 0ed54c6..70cd44d 100644
--- a/server/src/main/java/org/apache/iotdb/db/monitor/StatMonitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/monitor/StatMonitor.java
@@ -31,10 +31,9 @@ import org.apache.iotdb.db.concurrent.ThreadName;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.StorageEngine;
-import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.StartupException;
 import org.apache.iotdb.db.exception.StorageEngineException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.monitor.MonitorConstants.FileNodeManagerStatConstants;
@@ -44,10 +43,8 @@ import org.apache.iotdb.db.qp.physical.crud.InsertPlan;
 import org.apache.iotdb.db.service.IService;
 import org.apache.iotdb.db.service.ServiceType;
 import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
-import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
-import org.apache.iotdb.tsfile.read.common.Path;
 import org.apache.iotdb.tsfile.write.record.TSRecord;
 import org.apache.iotdb.tsfile.write.record.datapoint.LongDataPoint;
 import org.slf4j.Logger;
@@ -87,8 +84,8 @@ public class StatMonitor implements IService {
     if (config.isEnableStatMonitor()) {
       try {
         String prefix = MonitorConstants.STAT_STORAGE_GROUP_PREFIX;
-        if (!mmanager.pathExist(prefix)) {
-          mmanager.setStorageGroupToMTree(prefix);
+        if (!mmanager.isPathExist(prefix)) {
+          mmanager.setStorageGroup(prefix);
         }
       } catch (MetadataException e) {
         logger.error("MManager cannot set storage group to MTree.", e);
@@ -144,8 +141,8 @@ public class StatMonitor implements IService {
     MManager mManager = MManager.getInstance();
     String prefix = MonitorConstants.STAT_STORAGE_GROUP_PREFIX;
     try {
-      if (!mManager.pathExist(prefix)) {
-        mManager.setStorageGroupToMTree(prefix);
+      if (!mManager.isPathExist(prefix)) {
+        mManager.setStorageGroup(prefix);
       }
     } catch (Exception e) {
       logger.error("MManager cannot set storage group to MTree.", e);
@@ -165,14 +162,14 @@ public class StatMonitor implements IService {
           logger.error("Registering metadata but data type of {} is null", entry.getKey());
         }
 
-        if (!mManager.pathExist(entry.getKey())) {
-          mManager.addPathToMTree(new Path(entry.getKey()), TSDataType.valueOf(entry.getValue()),
+        if (!mManager.isPathExist(entry.getKey())) {
+          mManager.createTimeseries(entry.getKey(), TSDataType.valueOf(entry.getValue()),
               TSEncoding.valueOf("RLE"),
-              CompressionType.valueOf(TSFileDescriptor.getInstance().getConfig().getCompressor()),
+              TSFileDescriptor.getInstance().getConfig().getCompressor(),
               Collections.emptyMap());
         }
       }
-    } catch (MetadataException | PathException e) {
+    } catch (MetadataException e) {
       logger.error("Initialize the metadata error.", e);
     }
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/monitor/collector/FileSize.java b/server/src/main/java/org/apache/iotdb/db/monitor/collector/FileSize.java
index 1f52ac7..9e7dca3 100644
--- a/server/src/main/java/org/apache/iotdb/db/monitor/collector/FileSize.java
+++ b/server/src/main/java/org/apache/iotdb/db/monitor/collector/FileSize.java
@@ -37,9 +37,7 @@ import org.apache.iotdb.db.monitor.IStatistic;
 import org.apache.iotdb.db.monitor.MonitorConstants;
 import org.apache.iotdb.db.monitor.MonitorConstants.FileSizeConstants;
 import org.apache.iotdb.db.monitor.StatMonitor;
-import org.apache.iotdb.tsfile.common.conf.TSFileConfig;
 import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
-import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
 import org.apache.iotdb.tsfile.read.common.Path;
@@ -80,7 +78,7 @@ public class FileSize implements IStatistic {
       Path path = new Path(seriesPath);
       try {
         storageEngine.addTimeSeries(path, TSDataType.valueOf(MonitorConstants.DATA_TYPE_INT64),
-            TSEncoding.valueOf("RLE"), CompressionType.valueOf(TSFileDescriptor.getInstance().getConfig().getCompressor()),
+            TSEncoding.valueOf("RLE"), TSFileDescriptor.getInstance().getConfig().getCompressor(),
             Collections.emptyMap());
       } catch (StorageEngineException e) {
         logger.error("Register File Size Stats into storageEngine Failed.", e);
@@ -147,7 +145,7 @@ public class FileSize implements IStatistic {
             fileSizes.put(kinds, FileUtils.sizeOfDirectory(file));
           } catch (Exception e) {
             logger.error("Meet error while trying to get {} size with dir {} .", kinds,
-                    kinds.getPath(), e);
+                kinds.getPath(), e);
             fileSizes.put(kinds, ABNORMAL_VALUE);
           }
         } else {
@@ -158,7 +156,8 @@ public class FileSize implements IStatistic {
     return fileSizes;
   }
 
-  private long collectSeqFileSize(EnumMap<FileSizeConstants, Long> fileSizes, FileSizeConstants kinds) {
+  private long collectSeqFileSize(EnumMap<FileSizeConstants, Long> fileSizes,
+      FileSizeConstants kinds) {
     long fileSize = INIT_VALUE_IF_FILE_NOT_EXIST;
     for (String sequenceDir : config.getDataDirs()) {
       if (sequenceDir.contains("unsequence")) {
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/Planner.java b/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
index 666d40f..19a4d69 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/Planner.java
@@ -79,7 +79,6 @@ public class Planner {
       case DELETE_STORAGE_GROUP:
       case CREATE_TIMESERIES:
       case DELETE_TIMESERIES:
-      case PROPERTY:
       case LOADDATA:
       case INSERT:
       case INDEX:
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
index a37f78d..2cf135d 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
@@ -38,7 +38,6 @@ import static org.apache.iotdb.tsfile.common.constant.TsFileConstant.TSFILE_SUFF
 
 import java.io.File;
 import java.io.IOException;
-import java.sql.SQLException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -63,14 +62,14 @@ import org.apache.iotdb.db.engine.flush.pool.FlushTaskPoolManager;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
 import org.apache.iotdb.db.metadata.MManager;
-import org.apache.iotdb.db.metadata.MNode;
+import org.apache.iotdb.db.metadata.mnode.InternalMNode;
+import org.apache.iotdb.db.metadata.mnode.MNode;
+import org.apache.iotdb.db.metadata.mnode.StorageGroupMNode;
 import org.apache.iotdb.db.qp.logical.sys.AuthorOperator;
 import org.apache.iotdb.db.qp.logical.sys.AuthorOperator.AuthorType;
-import org.apache.iotdb.db.qp.logical.sys.PropertyOperator;
 import org.apache.iotdb.db.qp.physical.PhysicalPlan;
 import org.apache.iotdb.db.qp.physical.crud.AggregationPlan;
 import org.apache.iotdb.db.qp.physical.crud.AlignByDevicePlan;
@@ -89,7 +88,6 @@ import org.apache.iotdb.db.qp.physical.sys.DataAuthPlan;
 import org.apache.iotdb.db.qp.physical.sys.DeleteStorageGroupPlan;
 import org.apache.iotdb.db.qp.physical.sys.DeleteTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.OperateFilePlan;
-import org.apache.iotdb.db.qp.physical.sys.PropertyPlan;
 import org.apache.iotdb.db.qp.physical.sys.SetStorageGroupPlan;
 import org.apache.iotdb.db.qp.physical.sys.SetTTLPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowChildPathsPlan;
@@ -108,7 +106,6 @@ import org.apache.iotdb.db.utils.FileLoaderUtils;
 import org.apache.iotdb.db.utils.TypeInferenceUtils;
 import org.apache.iotdb.db.utils.UpgradeUtils;
 import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
-import org.apache.iotdb.tsfile.exception.cache.CacheException;
 import org.apache.iotdb.tsfile.exception.filter.QueryFilterOptimizationException;
 import org.apache.iotdb.tsfile.exception.write.UnSupportedDataTypeException;
 import org.apache.iotdb.tsfile.file.metadata.ChunkGroupMetaData;
@@ -151,7 +148,7 @@ public class PlanExecutor implements IPlanExecutor {
   @Override
   public QueryDataSet processQuery(PhysicalPlan queryPlan, QueryContext context)
       throws IOException, StorageEngineException, QueryFilterOptimizationException,
-      QueryProcessException, MetadataException, SQLException {
+      QueryProcessException, MetadataException {
     if (queryPlan instanceof QueryPlan) {
       return processDataQuery((QueryPlan) queryPlan, context);
     } else if (queryPlan instanceof AuthorPlan) {
@@ -202,10 +199,7 @@ public class PlanExecutor implements IPlanExecutor {
       case SET_STORAGE_GROUP:
         return setStorageGroup((SetStorageGroupPlan) plan);
       case DELETE_STORAGE_GROUP:
-        return deleteStorageGroup((DeleteStorageGroupPlan) plan);
-      case PROPERTY:
-        PropertyPlan property = (PropertyPlan) plan;
-        return operateProperty(property);
+        return deleteStorageGroups((DeleteStorageGroupPlan) plan);
       case TTL:
         operateTTL((SetTTLPlan) plan);
         return true;
@@ -253,7 +247,7 @@ public class PlanExecutor implements IPlanExecutor {
   }
 
   private QueryDataSet processShowQuery(ShowPlan showPlan)
-      throws QueryProcessException, MetadataException, SQLException {
+      throws QueryProcessException, MetadataException {
     switch (showPlan.getShowContentType()) {
       case TTL:
         return processShowTTLQuery((ShowTTLPlan) showPlan);
@@ -282,10 +276,11 @@ public class PlanExecutor implements IPlanExecutor {
     }
   }
 
-  private QueryDataSet processCountNodes(CountPlan countPlan) throws SQLException {
+  private QueryDataSet processCountNodes(CountPlan countPlan) throws MetadataException {
     List<String> nodes = getNodesList(countPlan.getPath().toString(), countPlan.getLevel());
     int num = nodes.size();
-    SingleDataSet singleDataSet = new SingleDataSet(Collections.singletonList(new Path(COLUMN_COUNT)),
+    SingleDataSet singleDataSet = new SingleDataSet(
+        Collections.singletonList(new Path(COLUMN_COUNT)),
         Collections.singletonList(TSDataType.INT32));
     Field field = new Field(TSDataType.INT32);
     field.setIntV(num);
@@ -295,10 +290,10 @@ public class PlanExecutor implements IPlanExecutor {
     return singleDataSet;
   }
 
-  private QueryDataSet processCountNodeTimeSeries(CountPlan countPlan)
-      throws SQLException, MetadataException {
+  private QueryDataSet processCountNodeTimeSeries(CountPlan countPlan) throws MetadataException {
     List<String> nodes = getNodesList(countPlan.getPath().toString(), countPlan.getLevel());
-    ListDataSet listDataSet = new ListDataSet(Arrays.asList(new Path(COLUMN_COLUMN), new Path(COLUMN_COUNT)),
+    ListDataSet listDataSet = new ListDataSet(
+        Arrays.asList(new Path(COLUMN_COLUMN), new Path(COLUMN_COUNT)),
         Arrays.asList(TSDataType.TEXT, TSDataType.TEXT));
     for (String columnPath : nodes) {
       RowRecord record = new RowRecord(0);
@@ -314,16 +309,17 @@ public class PlanExecutor implements IPlanExecutor {
   }
 
   protected List<String> getPaths(String path) throws MetadataException {
-    return MManager.getInstance().getPaths(path);
+    return MManager.getInstance().getAllTimeseriesName(path);
   }
 
-  private List<String> getNodesList(String schemaPattern, int level) throws SQLException {
+  private List<String> getNodesList(String schemaPattern, int level) throws MetadataException {
     return MManager.getInstance().getNodesList(schemaPattern, level);
   }
 
   private QueryDataSet processCountTimeSeries(CountPlan countPlan) throws MetadataException {
     int num = getPaths(countPlan.getPath().toString()).size();
-    SingleDataSet singleDataSet = new SingleDataSet(Collections.singletonList(new Path(COLUMN_CHILD_PATHS)),
+    SingleDataSet singleDataSet = new SingleDataSet(
+        Collections.singletonList(new Path(COLUMN_CHILD_PATHS)),
         Collections.singletonList(TSDataType.INT32));
     Field field = new Field(TSDataType.INT32);
     field.setIntV(num);
@@ -333,12 +329,13 @@ public class PlanExecutor implements IPlanExecutor {
     return singleDataSet;
   }
 
-  private QueryDataSet processShowDevices(ShowDevicesPlan showDevicesPlan) throws PathException {
+  private QueryDataSet processShowDevices(ShowDevicesPlan showDevicesPlan)
+      throws MetadataException {
     ListDataSet listDataSet = new ListDataSet(Collections.singletonList(new Path(COLUMN_DEVICES)),
         Collections.singletonList(TSDataType.TEXT));
     List<String> devices;
     devices = MManager.getInstance().getDevices(showDevicesPlan.getPath().toString());
-    for(String s: devices) {
+    for (String s : devices) {
       RowRecord record = new RowRecord(0);
       Field field = new Field(TSDataType.TEXT);
       field.setBinaryV(new Binary(s));
@@ -349,12 +346,13 @@ public class PlanExecutor implements IPlanExecutor {
   }
 
   private QueryDataSet processShowChildPaths(ShowChildPathsPlan showChildPathsPlan)
-      throws PathException {
+      throws MetadataException {
     Set<String> childPathsList = MManager.getInstance()
         .getChildNodePathInNextLevel(showChildPathsPlan.getPath().toString());
-    ListDataSet listDataSet = new ListDataSet(Collections.singletonList(new Path(COLUMN_CHILD_PATHS)),
+    ListDataSet listDataSet = new ListDataSet(
+        Collections.singletonList(new Path(COLUMN_CHILD_PATHS)),
         Collections.singletonList(TSDataType.TEXT));
-    for(String s: childPathsList) {
+    for (String s : childPathsList) {
       RowRecord record = new RowRecord(0);
       Field field = new Field(TSDataType.TEXT);
       field.setBinaryV(new Binary(s));
@@ -365,10 +363,11 @@ public class PlanExecutor implements IPlanExecutor {
   }
 
   private QueryDataSet processShowStorageGroup() {
-    ListDataSet listDataSet = new ListDataSet(Collections.singletonList(new Path(COLUMN_STORAGE_GROUP)),
+    ListDataSet listDataSet = new ListDataSet(
+        Collections.singletonList(new Path(COLUMN_STORAGE_GROUP)),
         Collections.singletonList(TSDataType.TEXT));
     List<String> storageGroupList = MManager.getInstance().getAllStorageGroupNames();
-    for(String s: storageGroupList) {
+    for (String s : storageGroupList) {
       RowRecord record = new RowRecord(0);
       Field field = new Field(TSDataType.TEXT);
       field.setBinaryV(new Binary(s));
@@ -378,19 +377,21 @@ public class PlanExecutor implements IPlanExecutor {
     return listDataSet;
   }
 
-  private QueryDataSet processShowTimeseries(ShowTimeSeriesPlan timeSeriesPlan) throws PathException {
+  private QueryDataSet processShowTimeseries(ShowTimeSeriesPlan timeSeriesPlan)
+      throws MetadataException {
     ListDataSet listDataSet = new ListDataSet(Arrays.asList(
         new Path(COLUMN_TIMESERIES),
         new Path(COLUMN_STORAGE_GROUP),
         new Path(COLUMN_TIMESERIES_DATATYPE),
         new Path(COLUMN_TIMESERIES_ENCODING),
         new Path(COLUMN_TIMESERIES_COMPRESSION)),
-        Arrays.asList(TSDataType.TEXT, TSDataType.TEXT, TSDataType.TEXT, TSDataType.TEXT, TSDataType.TEXT));
-    List<List<String>> timeseriesList = MManager.getInstance()
-        .getShowTimeseriesPath(timeSeriesPlan.getPath().toString());
-    for(List<String> list : timeseriesList) {
+        Arrays.asList(TSDataType.TEXT, TSDataType.TEXT, TSDataType.TEXT, TSDataType.TEXT,
+            TSDataType.TEXT));
+    List<String[]> timeseriesList = MManager.getInstance()
+        .getAllTimeseriesSchema(timeSeriesPlan.getPath().toString());
+    for (String[] list : timeseriesList) {
       RowRecord record = new RowRecord(0);
-      for(String s : list) {
+      for (String s : list) {
         Field field = new Field(TSDataType.TEXT);
         field.setBinaryV(new Binary(s));
         record.addField(field);
@@ -401,13 +402,14 @@ public class PlanExecutor implements IPlanExecutor {
   }
 
   private QueryDataSet processShowTTLQuery(ShowTTLPlan showTTLPlan) {
-    ListDataSet listDataSet = new ListDataSet(Arrays.asList(new Path(COLUMN_STORAGE_GROUP),new Path(COLUMN_TTL))
+    ListDataSet listDataSet = new ListDataSet(
+        Arrays.asList(new Path(COLUMN_STORAGE_GROUP), new Path(COLUMN_TTL))
         , Arrays.asList(TSDataType.TEXT, TSDataType.INT64));
     List<String> selectedSgs = showTTLPlan.getStorageGroups();
 
-    List<MNode> storageGroups = MManager.getInstance().getAllStorageGroups();
+    List<StorageGroupMNode> storageGroups = MManager.getInstance().getAllStorageGroupNodes();
     int timestamp = 0;
-    for (MNode mNode : storageGroups) {
+    for (StorageGroupMNode mNode : storageGroups) {
       String sgName = mNode.getFullPath();
       if (!selectedSgs.isEmpty() && !selectedSgs.contains(sgName)) {
         continue;
@@ -431,7 +433,8 @@ public class PlanExecutor implements IPlanExecutor {
   }
 
   private QueryDataSet processShowVersion() {
-    SingleDataSet singleDataSet = new SingleDataSet(Collections.singletonList(new Path(IoTDBConstant.COLUMN_VERSION)),
+    SingleDataSet singleDataSet = new SingleDataSet(
+        Collections.singletonList(new Path(IoTDBConstant.COLUMN_VERSION)),
         Collections.singletonList(TSDataType.TEXT));
     Field field = new Field(TSDataType.TEXT);
     field.setBinaryV(new Binary(IoTDBConstant.VERSION));
@@ -442,7 +445,8 @@ public class PlanExecutor implements IPlanExecutor {
   }
 
   private QueryDataSet processShowDynamicParameterQuery() {
-    ListDataSet listDataSet = new ListDataSet(Arrays.asList(new Path(COLUMN_PARAMETER), new Path(COLUMN_VALUE)),
+    ListDataSet listDataSet = new ListDataSet(
+        Arrays.asList(new Path(COLUMN_PARAMETER), new Path(COLUMN_VALUE)),
         Arrays.asList(TSDataType.TEXT, TSDataType.TEXT));
 
     int timestamp = 0;
@@ -465,7 +469,8 @@ public class PlanExecutor implements IPlanExecutor {
   }
 
   private QueryDataSet processShowFlushTaskInfo() {
-    ListDataSet listDataSet = new ListDataSet(Arrays.asList(new Path(COLUMN_ITEM), new Path(COLUMN_VALUE)),
+    ListDataSet listDataSet = new ListDataSet(
+        Arrays.asList(new Path(COLUMN_ITEM), new Path(COLUMN_VALUE)),
         Arrays.asList(TSDataType.TEXT, TSDataType.TEXT));
 
     int timestamp = 0;
@@ -495,14 +500,14 @@ public class PlanExecutor implements IPlanExecutor {
     try {
       Set<String> existingPaths = new HashSet<>();
       for (Path p : deletePlan.getPaths()) {
-        existingPaths.addAll(mManager.getPaths(p.getFullPath()));
+        existingPaths.addAll(mManager.getAllTimeseriesName(p.getFullPath()));
       }
       if (existingPaths.isEmpty()) {
         throw new QueryProcessException(
             "TimeSeries does not exist and its data cannot be deleted");
       }
       for (String onePath : existingPaths) {
-        if (!mManager.pathExist(onePath)) {
+        if (!mManager.isPathExist(onePath)) {
           throw new QueryProcessException(String
               .format("TimeSeries %s does not exist and its data cannot be deleted", onePath));
         }
@@ -582,23 +587,41 @@ public class PlanExecutor implements IPlanExecutor {
 
   private void createSchemaAutomatically(List<ChunkGroupMetaData> chunkGroupMetaDatas,
       Map<String, MeasurementSchema> knownSchemas, int sgLevel)
-      throws CacheException, QueryProcessException, MetadataException, StorageEngineException {
+      throws QueryProcessException, MetadataException, StorageEngineException {
     if (chunkGroupMetaDatas.isEmpty()) {
       return;
     }
     for (ChunkGroupMetaData chunkGroupMetaData : chunkGroupMetaDatas) {
       String device = chunkGroupMetaData.getDeviceID();
-      MNode node = mManager.getNodeByPathFromCache(device, true, sgLevel);
+      MNode node = mManager.getDeviceNodeWithAutoCreateStorageGroup(device, true, sgLevel);
       for (ChunkMetaData chunkMetaData : chunkGroupMetaData.getChunkMetaDataList()) {
-        String fullPath =
-            device + IoTDBConstant.PATH_SEPARATOR + chunkMetaData.getMeasurementUid();
-        MeasurementSchema schema = knownSchemas.get(chunkMetaData.getMeasurementUid());
+        String measurement = chunkMetaData.getMeasurementUid();
+        String fullPath = device + IoTDBConstant.PATH_SEPARATOR + measurement;
+        MeasurementSchema schema = knownSchemas.get(measurement);
         if (schema == null) {
           throw new MetadataException(String
-              .format("Can not get the schema of measurement [%s]",
-                  chunkMetaData.getMeasurementUid()));
+              .format("Can not get the schema of measurement [%s]", measurement));
+        }
+        if (!node.hasChild(measurement)) {
+          try {
+            boolean result = mManager
+                .createTimeseries(fullPath, schema.getType(), schema.getEncodingType(),
+                    schema.getCompressor(), Collections.emptyMap());
+            if (result) {
+              storageEngine
+                  .addTimeSeries(new Path(fullPath), schema.getType(), schema.getEncodingType(),
+                      schema.getCompressor(), Collections.emptyMap());
+            }
+          } catch (MetadataException e) {
+            if (!e.getMessage().contains("already exist")) {
+              throw e;
+            }
+          }
+        }
+        if (node.getChild(measurement) instanceof InternalMNode) {
+          throw new QueryProcessException(
+              String.format("Current Path is not leaf node. %s", fullPath));
         }
-        checkPathExists(node, fullPath, schema, true);
       }
     }
   }
@@ -636,7 +659,7 @@ public class PlanExecutor implements IPlanExecutor {
     try {
       MManager.getInstance().setTTL(plan.getStorageGroup(), plan.getDataTTL());
       StorageEngine.getInstance().setTTL(plan.getStorageGroup(), plan.getDataTTL());
-    } catch (PathException | StorageEngineException e) {
+    } catch (MetadataException | StorageEngineException e) {
       throw new QueryProcessException(e);
     } catch (IOException e) {
       throw new QueryProcessException(e.getMessage());
@@ -653,13 +676,13 @@ public class PlanExecutor implements IPlanExecutor {
     String deviceId = path.getDevice();
     String measurementId = path.getMeasurement();
     try {
-      if (!mManager.pathExist(path.getFullPath())) {
+      if (!mManager.isPathExist(path.getFullPath())) {
         throw new QueryProcessException(
             String.format("Time series %s does not exist.", path.getFullPath()));
       }
-      mManager.getStorageGroupNameByPath(path.getFullPath());
+      mManager.getStorageGroupName(path.getFullPath());
       storageEngine.delete(deviceId, measurementId, timestamp);
-    } catch (StorageGroupException | StorageEngineException e) {
+    } catch (MetadataException | StorageEngineException e) {
       throw new QueryProcessException(e);
     }
   }
@@ -670,71 +693,65 @@ public class PlanExecutor implements IPlanExecutor {
     try {
       String[] measurementList = insertPlan.getMeasurements();
       String deviceId = insertPlan.getDeviceId();
-      MNode node = mManager.getNodeByPathFromCache(deviceId);
+      MNode node = mManager.getDeviceNodeWithAutoCreateStorageGroup(deviceId);
       String[] strValues = insertPlan.getValues();
       TSDataType[] dataTypes = new TSDataType[measurementList.length];
 
       for (int i = 0; i < measurementList.length; i++) {
-        MNode measurementNode = checkPathExists(node, deviceId, measurementList[i], strValues[i]);
+        String measurement = measurementList[i];
+        if (!node.hasChild(measurement)) {
+          if (!IoTDBDescriptor.getInstance().getConfig().isAutoCreateSchemaEnabled()) {
+            throw new QueryProcessException(
+                String.format("Current deviceId[%s] does not contain measurement:%s",
+                    deviceId, measurement));
+          }
+          TSDataType dataType = TypeInferenceUtils.getPredictedDataType(strValues[i]);
+          Path path = new Path(deviceId, measurement);
+
+          boolean result = mManager
+              .createTimeseries(path.toString(), dataType, getDefaultEncoding(dataType),
+                  TSFileDescriptor.getInstance().getConfig().getCompressor(),
+                  Collections.emptyMap());
+          if (result) {
+            storageEngine.addTimeSeries(path, dataType, getDefaultEncoding(dataType));
+          }
+        }
+        MNode measurementNode = node.getChild(measurement);
+        if (measurementNode instanceof InternalMNode) {
+          throw new QueryProcessException(
+              String.format("Current Path is not leaf node. %s.%s", deviceId, measurement));
+        }
+
         dataTypes[i] = measurementNode.getSchema().getType();
       }
       insertPlan.setDataTypes(dataTypes);
       storageEngine.insert(insertPlan);
     } catch (PathException | StorageEngineException | MetadataException e) {
       throw new QueryProcessException(e);
-    } catch (CacheException e) {
-      throw new QueryProcessException(e.getMessage());
     }
   }
 
-  private MNode checkPathExists(MNode node, String deviceId, String measurement, String strValue)
-      throws MetadataException, QueryProcessException, StorageEngineException {
-    // check if timeseries exists
-    if (!node.hasChild(measurement)) {
-      if (!IoTDBDescriptor.getInstance().getConfig().isAutoCreateSchemaEnabled()) {
-        throw new QueryProcessException(
-            String.format("Current deviceId[%s] does not contain measurement:%s", deviceId,
-                measurement));
-      }
-      try {
-        addPathToMTree(deviceId, measurement, strValue);
-      } catch (MetadataException e) {
-        if (!e.getMessage().contains("already exist")) {
-          throw e;
-        }
-      }
-    }
-    MNode measurementNode = node.getChild(measurement);
-    if (!measurementNode.isLeaf()) {
-      throw new QueryProcessException(
-          String.format("Current Path is not leaf node. %s.%s", deviceId, measurement));
-    }
-    return measurementNode;
-  }
-
-  private void checkPathExists(MNode node, String fullPath, MeasurementSchema schema,
-      boolean autoCreateSchema)
-      throws QueryProcessException, StorageEngineException, MetadataException {
-    // check if timeseries exists
-    String measurement = schema.getMeasurementId();
-    if (!node.hasChild(measurement)) {
-      if (!autoCreateSchema) {
-        throw new QueryProcessException(
-            String.format("Path[%s] does not exist", fullPath));
-      }
-      try {
-        addPathToMTree(fullPath, schema.getType(), schema.getEncodingType(),
-            schema.getCompressor());
-      } catch (MetadataException e) {
-        if (!e.getMessage().contains("already exist")) {
-          throw e;
-        }
-      }
-    }
-    MNode measurementNode = node.getChild(measurement);
-    if (!measurementNode.isLeaf()) {
-      throw new QueryProcessException(
-          String.format("Current Path is not leaf node. %s", fullPath));
+  /**
+   * Get default encoding by dataType
+   */
+  private TSEncoding getDefaultEncoding(TSDataType dataType) {
+    IoTDBConfig conf = IoTDBDescriptor.getInstance().getConfig();
+    switch (dataType) {
+      case BOOLEAN:
+        return conf.getDefaultBooleanEncoding();
+      case INT32:
+        return conf.getDefaultInt32Encoding();
+      case INT64:
+        return conf.getDefaultInt64Encoding();
+      case FLOAT:
+        return conf.getDefaultFloatEncoding();
+      case DOUBLE:
+        return conf.getDefaultDoubleEncoding();
+      case TEXT:
+        return conf.getDefaultTextEncoding();
+      default:
+        throw new UnSupportedDataTypeException(
+            String.format("Data type %s is not supported.", dataType.toString()));
     }
   }
 
@@ -743,12 +760,11 @@ public class PlanExecutor implements IPlanExecutor {
     try {
       String[] measurementList = batchInsertPlan.getMeasurements();
       String deviceId = batchInsertPlan.getDeviceId();
-      MNode node = mManager.getNodeByPathFromCache(deviceId);
+      MNode node = mManager.getDeviceNodeWithAutoCreateStorageGroup(deviceId);
       TSDataType[] dataTypes = batchInsertPlan.getDataTypes();
       IoTDBConfig conf = IoTDBDescriptor.getInstance().getConfig();
 
       for (int i = 0; i < measurementList.length; i++) {
-
         // check if timeseries exists
         if (!node.hasChild(measurementList[i])) {
           if (!conf.isAutoCreateSchemaEnabled()) {
@@ -756,10 +772,19 @@ public class PlanExecutor implements IPlanExecutor {
                 String.format("Current deviceId[%s] does not contain measurement:%s",
                     deviceId, measurementList[i]));
           }
-          addPathToMTree(deviceId, measurementList[i], dataTypes[i]);
+          Path path = new Path(deviceId, measurementList[i]);
+          TSDataType dataType = dataTypes[i];
+          boolean result = mManager
+              .createTimeseries(path.getFullPath(), dataType, getDefaultEncoding(dataType),
+                  TSFileDescriptor.getInstance().getConfig().getCompressor(),
+                  Collections.emptyMap());
+          if (result) {
+            storageEngine
+                .addTimeSeries(path, dataType, getDefaultEncoding(dataType));
+          }
         }
         MNode measurementNode = node.getChild(measurementList[i]);
-        if (!measurementNode.isLeaf()) {
+        if (measurementNode instanceof InternalMNode) {
           throw new QueryProcessException(
               String.format("Current Path is not leaf node. %s.%s", deviceId, measurementList[i]));
         }
@@ -774,10 +799,8 @@ public class PlanExecutor implements IPlanExecutor {
       }
       return storageEngine.insertBatch(batchInsertPlan);
 
-    } catch (PathException | StorageEngineException | MetadataException e) {
+    } catch (StorageEngineException | MetadataException e) {
       throw new QueryProcessException(e);
-    } catch (CacheException e) {
-      throw new QueryProcessException(e.getMessage());
     }
   }
 
@@ -861,11 +884,12 @@ public class PlanExecutor implements IPlanExecutor {
     TSEncoding encoding = createTimeSeriesPlan.getEncoding();
     Map<String, String> props = createTimeSeriesPlan.getProps();
     try {
-      boolean result = mManager.addPathToMTree(path, dataType, encoding, compressor, props);
+      boolean result = mManager
+          .createTimeseries(path.getFullPath(), dataType, encoding, compressor, props);
       if (result) {
         storageEngine.addTimeSeries(path, dataType, encoding, compressor, props);
       }
-    } catch (StorageEngineException | MetadataException | PathException e) {
+    } catch (StorageEngineException | MetadataException e) {
       throw new QueryProcessException(e);
     }
     return true;
@@ -876,7 +900,10 @@ public class PlanExecutor implements IPlanExecutor {
     List<Path> deletePathList = deleteTimeSeriesPlan.getPaths();
     try {
       deleteDataOfTimeSeries(deletePathList);
-      Set<String> emptyStorageGroups = mManager.deletePaths(deletePathList, false);
+      Set<String> emptyStorageGroups = new HashSet<>();
+      for (Path path : deletePathList) {
+        emptyStorageGroups.addAll(mManager.deleteTimeseries(path.toString()));
+      }
       for (String deleteStorageGroup : emptyStorageGroups) {
         storageEngine.deleteAllDataFilesInOneStorageGroup(deleteStorageGroup);
       }
@@ -890,21 +917,22 @@ public class PlanExecutor implements IPlanExecutor {
       throws QueryProcessException {
     Path path = setStorageGroupPlan.getPath();
     try {
-      mManager.setStorageGroupToMTree(path.getFullPath());
+      mManager.setStorageGroup(path.getFullPath());
     } catch (MetadataException e) {
       throw new QueryProcessException(e);
     }
     return true;
   }
 
-  private boolean deleteStorageGroup(DeleteStorageGroupPlan deleteStorageGroupPlan)
+  private boolean deleteStorageGroups(DeleteStorageGroupPlan deleteStorageGroupPlan)
       throws QueryProcessException {
-    List<Path> deletePathList = deleteStorageGroupPlan.getPaths();
+    List<String> deletePathList = new ArrayList<>();
     try {
-      mManager.deleteStorageGroupsFromMTree(deletePathList);
-      for (Path storageGroupPath : deletePathList) {
+      for (Path storageGroupPath : deleteStorageGroupPlan.getPaths()) {
         storageEngine.deleteStorageGroup(storageGroupPath.getFullPath());
+        deletePathList.add(storageGroupPath.getFullPath());
       }
+      mManager.deleteStorageGroups(deletePathList);
     } catch (MetadataException e) {
       throw new QueryProcessException(e);
     }
@@ -925,36 +953,6 @@ public class PlanExecutor implements IPlanExecutor {
     }
   }
 
-  private boolean operateProperty(PropertyPlan propertyPlan) throws QueryProcessException {
-    PropertyOperator.PropertyType propertyType = propertyPlan.getPropertyType();
-    Path propertyPath = propertyPlan.getPropertyPath();
-    Path metadataPath = propertyPlan.getMetadataPath();
-    try {
-      switch (propertyType) {
-        case ADD_TREE:
-          mManager.addAPTree(propertyPath.getFullPath());
-          break;
-        case ADD_PROPERTY_LABEL:
-          mManager.addPathToPTree(propertyPath.getFullPath());
-          break;
-        case DELETE_PROPERTY_LABEL:
-          mManager.deletePathFromPTree(propertyPath.getFullPath());
-          break;
-        case ADD_PROPERTY_TO_METADATA:
-          mManager.linkMNodeToPTree(propertyPath.getFullPath(), metadataPath.getFullPath());
-          break;
-        case DEL_PROPERTY_FROM_METADATA:
-          mManager.unlinkMNodeFromPTree(propertyPath.getFullPath(), metadataPath.getFullPath());
-          break;
-        default:
-          throw new QueryProcessException("unknown namespace type:" + propertyType);
-      }
-    } catch (PathException | IOException | MetadataException e) {
-      throw new QueryProcessException("meet error in " + propertyType + " . " + e.getMessage());
-    }
-    return true;
-  }
-
   private QueryDataSet processAuthorQuery(AuthorPlan plan)
       throws QueryProcessException {
     AuthorType authorType = plan.getAuthorType();
@@ -1150,80 +1148,4 @@ public class PlanExecutor implements IPlanExecutor {
     }
     return dataSet;
   }
-
-  /**
-   * register with value
-   */
-  private void addPathToMTree(String deviceId, String measurementId, Object value)
-      throws PathException, MetadataException, StorageEngineException {
-    TSDataType predictedDataType = TypeInferenceUtils.getPredictedDataType(value);
-    Path path = new Path(deviceId, measurementId);
-    TSEncoding encoding = getDefaultEncoding(predictedDataType);
-    CompressionType compressionType =
-        CompressionType.valueOf(TSFileDescriptor.getInstance().getConfig().getCompressor());
-    addPathToMTree(path, predictedDataType, encoding, compressionType);
-  }
-
-  /**
-   * register with datatype
-   */
-  private void addPathToMTree(String deviceId, String measurementId, TSDataType dataType)
-      throws PathException, MetadataException, StorageEngineException {
-    Path path = new Path(deviceId, measurementId);
-    TSEncoding encoding = getDefaultEncoding(dataType);
-    CompressionType compressionType =
-        CompressionType.valueOf(TSFileDescriptor.getInstance().getConfig().getCompressor());
-    addPathToMTree(path, dataType, encoding, compressionType);
-  }
-
-  /**
-   * Add a seriesPath to MTree, register with datatype, encoding and compression
-   */
-  private void addPathToMTree(Path path, TSDataType dataType, TSEncoding encoding,
-      CompressionType compressionType)
-      throws PathException, MetadataException, StorageEngineException {
-    boolean result = mManager.addPathToMTree(
-        path, dataType, encoding, compressionType, Collections.emptyMap());
-    if (result) {
-      storageEngine.addTimeSeries(path, dataType, encoding, compressionType, Collections.emptyMap());
-    }
-  }
-
-  /**
-   * Add a seriesPath to MTree, register with datatype, encoding and compression
-   */
-  private void addPathToMTree(String path, TSDataType dataType, TSEncoding encoding,
-      CompressionType compressionType)
-      throws PathException, MetadataException, StorageEngineException {
-    boolean result = mManager.addPathToMTree(
-        path, dataType, encoding, compressionType, Collections.emptyMap());
-    if (result) {
-      storageEngine.addTimeSeries(new Path(path),
-          dataType, encoding, compressionType, Collections.emptyMap());
-    }
-  }
-
-  /**
-   * Get default encoding by dataType
-   */
-  private TSEncoding getDefaultEncoding(TSDataType dataType) {
-    IoTDBConfig conf = IoTDBDescriptor.getInstance().getConfig();
-    switch (dataType) {
-      case BOOLEAN:
-        return conf.getDefaultBooleanEncoding();
-      case INT32:
-        return conf.getDefaultInt32Encoding();
-      case INT64:
-        return conf.getDefaultInt64Encoding();
-      case FLOAT:
-        return conf.getDefaultFloatEncoding();
-      case DOUBLE:
-        return conf.getDefaultDoubleEncoding();
-      case TEXT:
-        return conf.getDefaultTextEncoding();
-      default:
-        throw new UnSupportedDataTypeException(
-            String.format("Data type %s is not supported.", dataType.toString()));
-    }
-  }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java
index 2dfd9ad..b9a44f2 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/Operator.java
@@ -68,7 +68,7 @@ public abstract class Operator {
   public enum OperatorType {
     SFW, JOIN, UNION, FILTER, GROUPBY, ORDERBY, LIMIT, SELECT, SEQTABLESCAN, HASHTABLESCAN,
     MERGEJOIN, FILEREAD, NULL, TABLESCAN, UPDATE, INSERT, BATCHINSERT, DELETE, BASIC_FUNC, IN, QUERY, MERGEQUERY,
-    AGGREGATION, AUTHOR, FROM, FUNC, LOADDATA, METADATA, PROPERTY, INDEX, INDEXQUERY, FILL,
+    AGGREGATION, AUTHOR, FROM, FUNC, LOADDATA, METADATA, INDEX, INDEXQUERY, FILL,
     SET_STORAGE_GROUP, CREATE_TIMESERIES, DELETE_TIMESERIES, CREATE_USER, DELETE_USER, MODIFY_PASSWORD,
     GRANT_USER_PRIVILEGE, REVOKE_USER_PRIVILEGE, GRANT_USER_ROLE, REVOKE_USER_ROLE, CREATE_ROLE,
     DELETE_ROLE, GRANT_ROLE_PRIVILEGE, REVOKE_ROLE_PRIVILEGE, LIST_USER, LIST_ROLE,
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/BasicFunctionOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/BasicFunctionOperator.java
index 8914cab..7fb5863 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/BasicFunctionOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/BasicFunctionOperator.java
@@ -19,7 +19,7 @@
 package org.apache.iotdb.db.qp.logical.crud;
 
 import java.util.Objects;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.query.LogicalOperatorException;
 import org.apache.iotdb.db.exception.runtime.SQLParserException;
 import org.apache.iotdb.db.metadata.MManager;
@@ -75,10 +75,10 @@ public class BasicFunctionOperator extends FunctionOperator {
 
   @Override
   protected Pair<IUnaryExpression, String> transformToSingleQueryFilter()
-      throws LogicalOperatorException, PathException {
-    TSDataType type = MManager.getInstance().getSeriesType(singlePath);
+      throws LogicalOperatorException, MetadataException {
+    TSDataType type = MManager.getInstance().getSeriesType(singlePath.toString());
     if (type == null) {
-      throw new PathException(
+      throw new MetadataException(
           "given seriesPath:{" + singlePath.getFullPath() + "} don't exist in metadata");
     }
     IUnaryExpression ret;
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java
index 3b1c86d..67f5946 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/FilterOperator.java
@@ -18,7 +18,12 @@
  */
 package org.apache.iotdb.db.qp.logical.crud;
 
-import org.apache.iotdb.db.exception.path.PathException;
+import static org.apache.iotdb.db.qp.constant.SQLConstant.KW_AND;
+import static org.apache.iotdb.db.qp.constant.SQLConstant.KW_OR;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.query.LogicalOperatorException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.qp.constant.SQLConstant;
@@ -31,12 +36,6 @@ import org.apache.iotdb.tsfile.read.filter.factory.FilterFactory;
 import org.apache.iotdb.tsfile.utils.Pair;
 import org.apache.iotdb.tsfile.utils.StringContainer;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.apache.iotdb.db.qp.constant.SQLConstant.KW_AND;
-import static org.apache.iotdb.db.qp.constant.SQLConstant.KW_OR;
-
 /**
  * This class is for filter operator and implements {@link Operator} . It may consist of more than
  * two child FilterOperators, but if it's not a leaf operator, the relation is the same among all of
@@ -114,7 +113,12 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato
    */
   public IExpression transformToExpression() throws QueryProcessException {
     if (isSingle) {
-      Pair<IUnaryExpression, String> ret = transformToSingleQueryFilter();
+      Pair<IUnaryExpression, String> ret;
+      try {
+        ret = transformToSingleQueryFilter();
+      } catch (MetadataException e) {
+        throw new QueryProcessException(e);
+      }
       return ret.left;
     } else {
       if (childOperators.isEmpty()) {
@@ -146,10 +150,10 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato
    *
    * @return - pair.left: UnaryQueryFilter constructed by its one child; pair.right: Path
    * represented by this child.
-   * @throws QueryProcessException exception in filter transforming
+   * @throws MetadataException exception in filter transforming
    */
   protected Pair<IUnaryExpression, String> transformToSingleQueryFilter()
-      throws LogicalOperatorException, PathException {
+      throws LogicalOperatorException, MetadataException {
     if (childOperators.isEmpty()) {
       throw new LogicalOperatorException(String.valueOf(tokenIntType),
           "TransformToSingleFilter: this filter is not a leaf, but it's empty.");
@@ -209,7 +213,7 @@ public class FilterOperator extends Operator implements Comparable<FilterOperato
     // if child is leaf, will execute BasicFunctionOperator.equals()
     FilterOperator operator = (FilterOperator) fil;
     return this.tokenIntType == operator.tokenIntType
-            && this.getChildren().equals(operator.getChildren());
+        && this.getChildren().equals(operator.getChildren());
   }
 
   @Override
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/InOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/InOperator.java
index 2ab0f23..3d99339 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/InOperator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/logical/crud/InOperator.java
@@ -24,7 +24,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.query.LogicalOperatorException;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.qp.logical.Operator;
@@ -76,10 +76,10 @@ public class InOperator extends FunctionOperator {
 
   @Override
   protected Pair<IUnaryExpression, String> transformToSingleQueryFilter()
-      throws LogicalOperatorException, PathException {
-    TSDataType type = MManager.getInstance().getSeriesType(singlePath);
+      throws LogicalOperatorException, MetadataException {
+    TSDataType type = MManager.getInstance().getSeriesType(singlePath.toString());
     if (type == null) {
-      throw new PathException(
+      throw new MetadataException(
           "given seriesPath:{" + singlePath.getFullPath() + "} don't exist in metadata");
     }
     IUnaryExpression ret;
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/PropertyOperator.java b/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/PropertyOperator.java
deleted file mode 100644
index 5160bee..0000000
--- a/server/src/main/java/org/apache/iotdb/db/qp/logical/sys/PropertyOperator.java
+++ /dev/null
@@ -1,106 +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.qp.logical.sys;
-
-import org.apache.iotdb.db.qp.logical.RootOperator;
-import org.apache.iotdb.tsfile.read.common.Path;
-
-/**
- * this class maintains information in Metadata.namespace statement
- */
-public class PropertyOperator extends RootOperator {
-
-  private final PropertyType propertyType;
-  private Path propertyPath;
-  private Path metadataPath;
-  public PropertyOperator(int tokenIntType, PropertyType type) {
-    super(tokenIntType);
-    propertyType = type;
-    operatorType = OperatorType.PROPERTY;
-  }
-
-  public Path getPropertyPath() {
-    return propertyPath;
-  }
-
-  public void setPropertyPath(Path propertyPath) {
-    this.propertyPath = propertyPath;
-  }
-
-  public Path getMetadataPath() {
-    return metadataPath;
-  }
-
-  public void setMetadataPath(Path metadataPath) {
-    this.metadataPath = metadataPath;
-  }
-
-  public PropertyType getPropertyType() {
-    return propertyType;
-  }
-
-  public enum PropertyType {
-    ADD_TREE, ADD_PROPERTY_LABEL, DELETE_PROPERTY_LABEL, ADD_PROPERTY_TO_METADATA, DEL_PROPERTY_FROM_METADATA;
-
-    /**
-     * deserialize short number.
-     *
-     * @param i short number
-     * @return NamespaceType
-     */
-    public static PropertyType deserialize(short i) {
-      switch (i) {
-        case 0:
-          return ADD_TREE;
-        case 1:
-          return ADD_PROPERTY_LABEL;
-        case 2:
-          return DELETE_PROPERTY_LABEL;
-        case 3:
-          return ADD_PROPERTY_TO_METADATA;
-        case 4:
-          return DEL_PROPERTY_FROM_METADATA;
-        default:
-          return null;
-      }
-    }
-
-    /**
-     * serialize.
-     *
-     * @return short number
-     */
-    public short serialize() {
-      switch (this) {
-        case ADD_TREE:
-          return 0;
-        case ADD_PROPERTY_LABEL:
-          return 1;
-        case DELETE_PROPERTY_LABEL:
-          return 2;
-        case ADD_PROPERTY_TO_METADATA:
-          return 3;
-        case DEL_PROPERTY_FROM_METADATA:
-          return 4;
-        default:
-          return -1;
-      }
-    }
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/PropertyPlan.java b/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/PropertyPlan.java
deleted file mode 100644
index e7e27e4..0000000
--- a/server/src/main/java/org/apache/iotdb/db/qp/physical/sys/PropertyPlan.java
+++ /dev/null
@@ -1,95 +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.qp.physical.sys;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import org.apache.iotdb.db.qp.logical.Operator;
-import org.apache.iotdb.db.qp.logical.sys.PropertyOperator;
-import org.apache.iotdb.db.qp.physical.PhysicalPlan;
-import org.apache.iotdb.tsfile.read.common.Path;
-
-/**
- * Manipulate property plan
- */
-public class PropertyPlan extends PhysicalPlan {
-
-  private final PropertyOperator.PropertyType propertyType;
-  private Path propertyPath;
-  private Path metadataPath;
-
-  public PropertyPlan(PropertyOperator.PropertyType propertyType, Path propertyPath,
-      Path metadataPath) {
-    super(false, Operator.OperatorType.PROPERTY);
-    this.propertyType = propertyType;
-    this.propertyPath = propertyPath;
-    this.metadataPath = metadataPath;
-  }
-
-  public Path getPropertyPath() {
-    return propertyPath;
-  }
-
-  public Path getMetadataPath() {
-    return metadataPath;
-  }
-
-  public PropertyOperator.PropertyType getPropertyType() {
-    return propertyType;
-  }
-
-  @Override
-  public String toString() {
-    return "propertyPath: " + propertyPath.toString() + "\nmetadataPath: " + metadataPath
-        + "\npropertyType: "
-        + propertyType;
-  }
-
-  @Override
-  public List<Path> getPaths() {
-    List<Path> ret = new ArrayList<>();
-    if (metadataPath != null) {
-      ret.add(metadataPath);
-    }
-    if (propertyPath != null) {
-      ret.add(propertyPath);
-    }
-    return ret;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-    PropertyPlan that = (PropertyPlan) o;
-    return propertyType == that.propertyType &&
-        Objects.equals(propertyPath, that.propertyPath) &&
-        Objects.equals(metadataPath, that.metadataPath);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(propertyType, propertyPath, metadataPath);
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
index e6ec3af..9c5d837 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/LogicalGenerator.java
@@ -53,7 +53,6 @@ import org.apache.iotdb.db.qp.logical.sys.LoadConfigurationOperator;
 import org.apache.iotdb.db.qp.logical.sys.LoadDataOperator;
 import org.apache.iotdb.db.qp.logical.sys.LoadFilesOperator;
 import org.apache.iotdb.db.qp.logical.sys.MoveFileOperator;
-import org.apache.iotdb.db.qp.logical.sys.PropertyOperator;
 import org.apache.iotdb.db.qp.logical.sys.RemoveFileOperator;
 import org.apache.iotdb.db.qp.logical.sys.SetStorageGroupOperator;
 import org.apache.iotdb.db.qp.logical.sys.SetTTLOperator;
@@ -62,7 +61,6 @@ import org.apache.iotdb.db.qp.logical.sys.ShowDevicesOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowTTLOperator;
 import org.apache.iotdb.db.qp.logical.sys.ShowTimeSeriesOperator;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AddLabelContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AlignByDeviceClauseContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AlterUserContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AndExpressionContext;
@@ -71,12 +69,10 @@ import org.apache.iotdb.db.qp.strategy.SqlBaseParser.AutoCreateSchemaContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ConstantContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CountNodesContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CountTimeseriesContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreatePropertyContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateRoleContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateTimeseriesContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.CreateUserContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DateExpressionContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeleteLabelContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeleteStatementContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeleteStorageGroupContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.DeleteTimeseriesContext;
@@ -96,7 +92,6 @@ import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertColumnSpecContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertStatementContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.InsertValuesSpecContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LimitClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.LinkPathContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListAllRoleOfUserContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListAllUserOfRoleContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.ListPrivilegesRoleContext;
@@ -142,7 +137,6 @@ import org.apache.iotdb.db.qp.strategy.SqlBaseParser.SuffixPathContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TimeIntervalContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TimeseriesPathContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.TypeClauseContext;
-import org.apache.iotdb.db.qp.strategy.SqlBaseParser.UnlinkPathContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.UnsetTTLStatementContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.UpdateStatementContext;
 import org.apache.iotdb.db.qp.strategy.SqlBaseParser.WhereClauseContext;
@@ -308,64 +302,6 @@ public class LogicalGenerator extends SqlBaseBaseListener {
   }
 
   @Override
-  public void enterCreateProperty(CreatePropertyContext ctx) {
-    super.enterCreateProperty(ctx);
-    PropertyOperator propertyOperator = new PropertyOperator(SQLConstant.TOK_PROPERTY_CREATE,
-        PropertyOperator.PropertyType.ADD_TREE);
-    propertyOperator.setPropertyPath(new Path(ctx.ID().getText()));
-    initializedOperator = propertyOperator;
-    operatorType = SQLConstant.TOK_PROPERTY_CREATE;
-  }
-
-  @Override
-  public void enterAddLabel(AddLabelContext ctx) {
-    super.enterAddLabel(ctx);
-    PropertyOperator propertyOperator = new PropertyOperator(SQLConstant.TOK_PROPERTY_ADD_LABEL,
-        PropertyOperator.PropertyType.ADD_PROPERTY_LABEL);
-    propertyOperator
-        .setPropertyPath(new Path(new String[]{ctx.ID(1).getText(), ctx.ID(0).getText()}));
-    initializedOperator = propertyOperator;
-    operatorType = SQLConstant.TOK_PROPERTY_ADD_LABEL;
-  }
-
-  @Override
-  public void enterDeleteLabel(DeleteLabelContext ctx) {
-    super.enterDeleteLabel(ctx);
-    PropertyOperator propertyOperator = new PropertyOperator(SQLConstant.TOK_PROPERTY_DELETE_LABEL,
-        PropertyOperator.PropertyType.DELETE_PROPERTY_LABEL);
-    propertyOperator
-        .setPropertyPath(new Path(new String[]{ctx.ID(1).getText(), ctx.ID(0).getText()}));
-    initializedOperator = propertyOperator;
-    operatorType = SQLConstant.TOK_PROPERTY_DELETE_LABEL;
-  }
-
-  @Override
-  public void enterLinkPath(LinkPathContext ctx) {
-    super.enterLinkPath(ctx);
-    PropertyOperator propertyOperator = new PropertyOperator(SQLConstant.TOK_PROPERTY_LINK,
-        PropertyOperator.PropertyType.ADD_PROPERTY_TO_METADATA);
-    Path metaPath = parsePrefixPath(ctx.prefixPath());
-    propertyOperator.setMetadataPath(metaPath);
-    propertyOperator.setPropertyPath(new Path(new String[]{ctx.propertyLabelPair().ID(0).getText()
-        , ctx.propertyLabelPair().ID(1).getText()}));
-    initializedOperator = propertyOperator;
-    operatorType = SQLConstant.TOK_PROPERTY_LINK;
-  }
-
-  @Override
-  public void enterUnlinkPath(UnlinkPathContext ctx) {
-    super.enterUnlinkPath(ctx);
-    PropertyOperator propertyOperator = new PropertyOperator(SQLConstant.TOK_PROPERTY_UNLINK,
-        PropertyOperator.PropertyType.DEL_PROPERTY_FROM_METADATA);
-    Path metaPath = parsePrefixPath(ctx.prefixPath());
-    propertyOperator.setMetadataPath(metaPath);
-    propertyOperator.setPropertyPath(new Path(new String[]{ctx.propertyLabelPair().ID(0).getText()
-        , ctx.propertyLabelPair().ID(1).getText()}));
-    initializedOperator = propertyOperator;
-    operatorType = SQLConstant.TOK_PROPERTY_UNLINK;
-  }
-
-  @Override
   public void enterCreateUser(CreateUserContext ctx) {
     super.enterCreateUser(ctx);
     AuthorOperator authorOperator = new AuthorOperator(SQLConstant.TOK_AUTHOR_CREATE,
@@ -954,22 +890,22 @@ public class LogicalGenerator extends SqlBaseBaseListener {
     String encoding = ctx.encoding().getChild(0).getText().toUpperCase();
     createTimeSeriesOperator.setDataType(TSDataType.valueOf(dataType));
     createTimeSeriesOperator.setEncoding(TSEncoding.valueOf(encoding));
-    String compressor;
+    CompressionType compressor;
     List<PropertyContext> properties = ctx.property();
     Map<String, String> props = new HashMap<>(properties.size(), 1);
     if (ctx.propertyValue() != null) {
-      compressor = ctx.propertyValue().getText().toUpperCase();
+      compressor = CompressionType.valueOf(ctx.propertyValue().getText().toUpperCase());
     } else {
-      compressor = TSFileDescriptor.getInstance().getConfig().getCompressor().toUpperCase();
+      compressor = TSFileDescriptor.getInstance().getConfig().getCompressor();
     }
-    checkMetadataArgs(dataType, encoding, compressor);
+    checkMetadataArgs(dataType, encoding, compressor.toString().toUpperCase());
     if (ctx.property(0) != null) {
       for (PropertyContext property : properties) {
         props.put(property.ID().getText().toLowerCase(),
             property.propertyValue().getText().toLowerCase());
       }
     }
-    createTimeSeriesOperator.setCompressor(CompressionType.valueOf(compressor));
+    createTimeSeriesOperator.setCompressor(compressor);
     createTimeSeriesOperator.setProps(props);
     initializedOperator = createTimeSeriesOperator;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
index 61c16c0..ee44e56 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/PhysicalGenerator.java
@@ -28,7 +28,6 @@ import java.util.Map;
 import java.util.Set;
 import org.apache.iotdb.db.auth.AuthException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
 import org.apache.iotdb.db.exception.query.LogicalOperatorException;
 import org.apache.iotdb.db.exception.query.LogicalOptimizeException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
@@ -50,7 +49,6 @@ import org.apache.iotdb.db.qp.logical.sys.DeleteTimeSeriesOperator;
 import org.apache.iotdb.db.qp.logical.sys.LoadDataOperator;
 import org.apache.iotdb.db.qp.logical.sys.LoadFilesOperator;
 import org.apache.iotdb.db.qp.logical.sys.MoveFileOperator;
-import org.apache.iotdb.db.qp.logical.sys.PropertyOperator;
 import org.apache.iotdb.db.qp.logical.sys.RemoveFileOperator;
 import org.apache.iotdb.db.qp.logical.sys.SetStorageGroupOperator;
 import org.apache.iotdb.db.qp.logical.sys.SetTTLOperator;
@@ -76,7 +74,6 @@ import org.apache.iotdb.db.qp.physical.sys.DeleteTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.LoadConfigurationPlan;
 import org.apache.iotdb.db.qp.physical.sys.LoadDataPlan;
 import org.apache.iotdb.db.qp.physical.sys.OperateFilePlan;
-import org.apache.iotdb.db.qp.physical.sys.PropertyPlan;
 import org.apache.iotdb.db.qp.physical.sys.SetStorageGroupPlan;
 import org.apache.iotdb.db.qp.physical.sys.SetTTLPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowChildPathsPlan;
@@ -129,10 +126,6 @@ public class PhysicalGenerator {
       case DELETE_TIMESERIES:
         DeleteTimeSeriesOperator deletePath = (DeleteTimeSeriesOperator) operator;
         return new DeleteTimeSeriesPlan(deletePath.getDeletePathList());
-      case PROPERTY:
-        PropertyOperator property = (PropertyOperator) operator;
-        return new PropertyPlan(property.getPropertyType(), property.getPropertyPath(),
-            property.getMetadataPath());
       case DELETE:
         DeleteDataOperator delete = (DeleteDataOperator) operator;
         paths = delete.getSelectedPaths();
@@ -289,7 +282,7 @@ public class PhysicalGenerator {
           Path fullPath = Path.addPrefixPath(suffixPath, device);
           try {
             List<String> actualPaths = MManager.getInstance()
-                .getPaths(fullPath.getFullPath());  // remove stars in SELECT to get actual paths
+                .getAllTimeseriesName(fullPath.getFullPath());  // remove stars in SELECT to get actual paths
 
             // for actual non exist path
             if (actualPaths.isEmpty() && originAggregations.isEmpty()) {
@@ -397,7 +390,11 @@ public class PhysicalGenerator {
         ((RawDataQueryPlan) queryPlan).setExpression(expression);
       }
     }
-    generateDataTypes(queryPlan);
+    try {
+      generateDataTypes(queryPlan);
+    } catch (MetadataException e) {
+      throw new QueryProcessException(e);
+    }
     deduplicate(queryPlan);
 
     queryPlan.setRowLimit(queryOperator.getRowLimit());
@@ -435,7 +432,7 @@ public class PhysicalGenerator {
         deviceSet.addAll(tempDS);
       }
       retDevices = new ArrayList<>(deviceSet);
-    } catch (PathException e) {
+    } catch (MetadataException e) {
       throw new LogicalOptimizeException("error when remove star: " + e.getMessage());
     }
     return retDevices;
@@ -460,11 +457,11 @@ public class PhysicalGenerator {
     basicOperator.setSinglePath(concatPath);
   }
 
-  private void generateDataTypes(QueryPlan queryPlan) throws PathException {
+  private void generateDataTypes(QueryPlan queryPlan) throws MetadataException {
     List<Path> paths = queryPlan.getPaths();
     List<TSDataType> dataTypes = new ArrayList<>(paths.size());
     for (Path path : paths) {
-      TSDataType seriesType = MManager.getInstance().getSeriesType(path);
+      TSDataType seriesType = MManager.getInstance().getSeriesType(path.toString());
       dataTypes.add(seriesType);
       queryPlan.addTypeMapping(path, seriesType);
     }
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
index b960511..bd36fa4 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/strategy/optimizer/ConcatPathOptimizer.java
@@ -268,7 +268,7 @@ public class ConcatPathOptimizer implements ILogicalOptimizer {
     LinkedHashMap<String, Integer> pathMap = new LinkedHashMap<>();
     try {
       for (Path path : paths) {
-        List<String> all = MManager.getInstance().getPaths(path.getFullPath());
+        List<String> all = MManager.getInstance().getAllTimeseriesName(path.getFullPath());
         for (String subPath : all) {
           if (!pathMap.containsKey(subPath)) {
             pathMap.put(subPath, 1);
@@ -290,7 +290,7 @@ public class ConcatPathOptimizer implements ILogicalOptimizer {
     List<String> newAggregations = new ArrayList<>();
     for (int i = 0; i < paths.size(); i++) {
       try {
-        List<String> actualPaths = MManager.getInstance().getPaths(paths.get(i).getFullPath());
+        List<String> actualPaths = MManager.getInstance().getAllTimeseriesName(paths.get(i).getFullPath());
         for (String actualPath : actualPaths) {
           retPaths.add(new Path(actualPath));
           if (afterConcatAggregations != null && !afterConcatAggregations.isEmpty()) {
diff --git a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithValueFilterDataSet.java b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithValueFilterDataSet.java
index e88c351..55241c4 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithValueFilterDataSet.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/dataset/groupby/GroupByWithValueFilterDataSet.java
@@ -21,7 +21,7 @@ package org.apache.iotdb.db.query.dataset.groupby;
 
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.exception.StorageEngineException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.qp.physical.crud.GroupByPlan;
 import org.apache.iotdb.db.query.aggregation.AggregateResult;
 import org.apache.iotdb.db.query.context.QueryContext;
diff --git a/server/src/main/java/org/apache/iotdb/db/query/executor/AggregationExecutor.java b/server/src/main/java/org/apache/iotdb/db/query/executor/AggregationExecutor.java
index 40cd769..7c49a88 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/executor/AggregationExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/executor/AggregationExecutor.java
@@ -28,7 +28,7 @@ import java.util.Map;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.querycontext.QueryDataSource;
 import org.apache.iotdb.db.exception.StorageEngineException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.qp.physical.crud.AggregationPlan;
 import org.apache.iotdb.db.query.aggregation.AggregateResult;
diff --git a/server/src/main/java/org/apache/iotdb/db/query/factory/AggreResultFactory.java b/server/src/main/java/org/apache/iotdb/db/query/factory/AggreResultFactory.java
index e60d441..77f91c8 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/factory/AggreResultFactory.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/factory/AggreResultFactory.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.db.query.factory;
 
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.qp.constant.SQLConstant;
 import org.apache.iotdb.db.query.aggregation.AggregateResult;
 import org.apache.iotdb.db.query.aggregation.impl.AvgAggrResult;
diff --git a/server/src/main/java/org/apache/iotdb/db/query/timegenerator/ServerTimeGenerator.java b/server/src/main/java/org/apache/iotdb/db/query/timegenerator/ServerTimeGenerator.java
index fdb4d3e..28fcd4e 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/timegenerator/ServerTimeGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/timegenerator/ServerTimeGenerator.java
@@ -54,7 +54,6 @@ public class ServerTimeGenerator extends TimeGenerator {
     }
   }
 
-
   @Override
   protected IBatchReader generateNewBatchReader(SingleSeriesExpression expression)
       throws IOException {
diff --git a/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
index acab66a..b2a8f71 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
@@ -54,9 +54,9 @@ import org.apache.iotdb.db.engine.StorageEngine;
 import org.apache.iotdb.db.exception.QueryInBatchStatementException;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
+import org.apache.iotdb.db.exception.metadata.StorageGroupNotSetException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.exception.runtime.SQLParserException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupNotSetException;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.metrics.server.SqlArgument;
 import org.apache.iotdb.db.qp.Planner;
@@ -78,8 +78,8 @@ import org.apache.iotdb.db.qp.physical.sys.SetStorageGroupPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowPlan;
 import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.query.control.QueryResourceManager;
-import org.apache.iotdb.db.query.dataset.RawQueryDataSetWithoutValueFilter;
 import org.apache.iotdb.db.query.dataset.NonAlignEngineDataSet;
+import org.apache.iotdb.db.query.dataset.RawQueryDataSetWithoutValueFilter;
 import org.apache.iotdb.db.tools.watermark.GroupedLSBWatermarkEncoder;
 import org.apache.iotdb.db.tools.watermark.WatermarkEncoder;
 import org.apache.iotdb.db.utils.QueryDataSetUtils;
@@ -204,7 +204,14 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
           throw new QueryProcessException("aggregate does not support " + aggrType + " function.");
       }
     }
-    return MManager.getInstance().getSeriesType(path);
+    TSDataType dataType;
+    try {
+      dataType = MManager.getInstance().getSeriesType(path);
+    } catch (MetadataException e) {
+      throw new QueryProcessException(e);
+    }
+
+    return dataType;
   }
 
   @Override
@@ -347,7 +354,7 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
   /**
    * convert from TSStatusCode to TSStatus, which has message appending with existed status message
    *
-   * @param statusType    status type
+   * @param statusType status type
    * @param appendMessage appending message
    */
   private TSStatus getStatus(TSStatusCode statusType, String appendMessage) {
@@ -400,7 +407,7 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
   }
 
   protected List<String> getPaths(String path) throws MetadataException {
-    return MManager.getInstance().getPaths(path);
+    return MManager.getInstance().getAllTimeseriesName(path);
   }
 
   /**
@@ -593,7 +600,7 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
 
   /**
    * @param plan must be a plan for Query: FillQueryPlan, AggregationPlan, GroupByPlan, some
-   *             AuthorPlan
+   * AuthorPlan
    */
   private TSExecuteStatementResp executeQueryStatement(
       long statementId, PhysicalPlan plan, int fetchSize, String username) {
diff --git a/server/src/main/java/org/apache/iotdb/db/sync/receiver/transfer/SyncServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/sync/receiver/transfer/SyncServiceImpl.java
index d0c3d27..6096a53 100644
--- a/server/src/main/java/org/apache/iotdb/db/sync/receiver/transfer/SyncServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/sync/receiver/transfer/SyncServiceImpl.java
@@ -33,9 +33,8 @@ import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.conf.directories.DirectoryManager;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.DiskSpaceInsufficientException;
-import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
 import org.apache.iotdb.db.exception.SyncDeviceOwnerConflictException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.metadata.MetadataConstant;
 import org.apache.iotdb.db.sync.conf.SyncConstant;
@@ -259,7 +258,7 @@ public class SyncServiceImpl implements SyncService.Iface {
         while ((metadataOperation = br.readLine()) != null) {
           try {
             MManager.getInstance().operation(metadataOperation);
-          } catch (IOException | MetadataException | PathException e) {
+          } catch (IOException | MetadataException e) {
             logger.error("Can not operate metadata operation {} ", metadataOperation, e);
           }
         }
diff --git a/server/src/main/java/org/apache/iotdb/db/sync/sender/manage/SyncFileManager.java b/server/src/main/java/org/apache/iotdb/db/sync/sender/manage/SyncFileManager.java
index 83b7345..6c4c569 100644
--- a/server/src/main/java/org/apache/iotdb/db/sync/sender/manage/SyncFileManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/sync/sender/manage/SyncFileManager.java
@@ -35,7 +35,7 @@ import org.apache.iotdb.db.conf.IoTDBConstant;
 import org.apache.iotdb.db.engine.merge.task.MergeTask;
 import org.apache.iotdb.db.engine.modification.ModificationFile;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.sync.conf.SyncSenderDescriptor;
 import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
@@ -103,12 +103,12 @@ public class SyncFileManager implements ISyncFileManager {
         continue;
       }
       try {
-        if (!MManager.getInstance().getStorageGroupNameByPath(sgFolder.getName())
+        if (!MManager.getInstance().getStorageGroupName(sgFolder.getName())
             .equals(sgFolder.getName())) {
           // the folder is not a sg folder
           continue;
         }
-      } catch (StorageGroupException e) {
+      } catch (MetadataException e) {
         // the folder is not a sg folder
         continue;
       }
@@ -135,7 +135,7 @@ public class SyncFileManager implements ISyncFileManager {
           if (!file.getName().endsWith(TSFILE_SUFFIX)) {
             continue;
           }
-          if(checkFileValidity(file)){
+          if (checkFileValidity(file)) {
             currentSealedLocalFilesMap.get(sgName).get(timeRangeId).add(file);
           }
         }
@@ -143,7 +143,7 @@ public class SyncFileManager implements ISyncFileManager {
     }
   }
 
-  private boolean checkFileValidity(File file){
+  private boolean checkFileValidity(File file) {
     return new File(file.getAbsolutePath() + TsFileResource.RESOURCE_SUFFIX).exists()
         && !new File(
         file.getAbsolutePath() + ModificationFile.FILE_SUFFIX).exists() && !new File(
@@ -182,7 +182,7 @@ public class SyncFileManager implements ISyncFileManager {
     for (String sgName : allSGs.keySet()) {
       toBeSyncedFilesMap.putIfAbsent(sgName, new HashMap<>());
       deletedFilesMap.putIfAbsent(sgName, new HashMap<>());
-      for(Entry<Long, Set<File>> entry: currentSealedLocalFilesMap
+      for (Entry<Long, Set<File>> entry : currentSealedLocalFilesMap
           .getOrDefault(sgName, Collections.emptyMap()).entrySet()) {
         Long timeRangeId = entry.getKey();
         toBeSyncedFilesMap.get(sgName).putIfAbsent(timeRangeId, new HashSet<>());
diff --git a/server/src/main/java/org/apache/iotdb/db/utils/RandomDeleteCache.java b/server/src/main/java/org/apache/iotdb/db/utils/RandomDeleteCache.java
index 85912be..90921ce 100644
--- a/server/src/main/java/org/apache/iotdb/db/utils/RandomDeleteCache.java
+++ b/server/src/main/java/org/apache/iotdb/db/utils/RandomDeleteCache.java
@@ -44,30 +44,26 @@ public abstract class RandomDeleteCache<K, V> implements Cache<K, V> {
     return v;
   }
 
-  private void randomRemoveObjectIfCacheIsFull() throws CacheException {
+  private void randomRemoveObjectIfCacheIsFull() {
     if (cache.size() == this.cacheSize) {
       removeFirstObject();
     }
   }
 
-  private void removeFirstObject() throws CacheException {
+  private void removeFirstObject() {
     if (cache.size() == 0) {
       return;
     }
     K key = cache.keySet().iterator().next();
-    beforeRemove(cache.get(key));
     cache.remove(key);
   }
 
-  /**
-   * Do something before remove object from cache.
-   *
-   * @param object value of k-v pair
-   */
-  public abstract void beforeRemove(V object) throws CacheException;
-
   public abstract V loadObjectByKey(K key) throws CacheException;
 
+  public void removeObject(K key) {
+    cache.remove(key);
+  }
+
   @Override
   public void clear() {
     cache.clear();
diff --git a/server/src/main/java/org/apache/iotdb/db/utils/SchemaUtils.java b/server/src/main/java/org/apache/iotdb/db/utils/SchemaUtils.java
index 6ce9d4c..c18ce58 100644
--- a/server/src/main/java/org/apache/iotdb/db/utils/SchemaUtils.java
+++ b/server/src/main/java/org/apache/iotdb/db/utils/SchemaUtils.java
@@ -19,31 +19,32 @@
 package org.apache.iotdb.db.utils;
 
 import java.util.List;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.metadata.MManager;
-import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
-import org.apache.iotdb.tsfile.write.schema.Schema;
 import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+import org.apache.iotdb.tsfile.write.schema.Schema;
 
 
 public class SchemaUtils {
 
-  private SchemaUtils(){}
+  private SchemaUtils() {
+  }
 
   /**
    * Construct the Schema of the FileNode named processorName.
+   *
    * @param processorName the name of a FileNode.
    * @return the schema of the FileNode named processorName.
-   * @throws WriteProcessException when the fileSchema cannot be created.
    */
-  public static Schema constructSchema(String processorName) {
+  public static Schema constructSchema(String processorName) throws MetadataException {
     List<MeasurementSchema> columnSchemaList;
-    columnSchemaList = MManager.getInstance().getSchemaForStorageGroup(processorName);
+    columnSchemaList = MManager.getInstance().getStorageGroupSchema(processorName);
     return getSchemaFromColumnSchema(columnSchemaList);
   }
 
   /**
-   * getSchemaFromColumnSchema construct a Schema using the schema of the columns and the
-   * device type.
+   * getSchemaFromColumnSchema construct a Schema using the schema of the columns and device type.
+   *
    * @param schemaList the schema of the columns in this file.
    * @return a Schema contains the provided schemas.
    */
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/MetadataManagerHelper.java b/server/src/test/java/org/apache/iotdb/db/engine/MetadataManagerHelper.java
index db63179..76c0bb9 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/MetadataManagerHelper.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/MetadataManagerHelper.java
@@ -24,67 +24,63 @@ import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
-import org.apache.iotdb.tsfile.read.common.Path;
 
 public class MetadataManagerHelper {
 
-  private static MManager mmanager = null;
-
   public static void initMetadata() {
-    mmanager = MManager.getInstance();
+    MManager mmanager = MManager.getInstance();
     mmanager.init();
     mmanager.clear();
     try {
-      mmanager.setStorageGroupToMTree("root.vehicle.d0");
-      mmanager.setStorageGroupToMTree("root.vehicle.d1");
-      mmanager.setStorageGroupToMTree("root.vehicle.d2");
+      mmanager.setStorageGroup("root.vehicle.d0");
+      mmanager.setStorageGroup("root.vehicle.d1");
+      mmanager.setStorageGroup("root.vehicle.d2");
 
-      CompressionType compressionType =CompressionType.valueOf(
-          TSFileDescriptor.getInstance().getConfig().getCompressor());
+      CompressionType compressionType = TSFileDescriptor.getInstance().getConfig().getCompressor();
 
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s0"), TSDataType.valueOf("INT32"),
+      mmanager.createTimeseries("root.vehicle.d0.s0", TSDataType.valueOf("INT32"),
           TSEncoding.valueOf("RLE"), compressionType,
           Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s1"), TSDataType.valueOf("INT64"),
+      mmanager.createTimeseries("root.vehicle.d0.s1", TSDataType.valueOf("INT64"),
           TSEncoding.valueOf("RLE"), compressionType,
           Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s2"), TSDataType.valueOf("FLOAT"),
+      mmanager.createTimeseries("root.vehicle.d0.s2", TSDataType.valueOf("FLOAT"),
           TSEncoding.valueOf("RLE"), compressionType,
           Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s3"), TSDataType.valueOf("DOUBLE"),
+      mmanager.createTimeseries("root.vehicle.d0.s3", TSDataType.valueOf("DOUBLE"),
           TSEncoding.valueOf("RLE"), compressionType,
           Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s4"), TSDataType.valueOf("BOOLEAN"),
+      mmanager.createTimeseries("root.vehicle.d0.s4", TSDataType.valueOf("BOOLEAN"),
           TSEncoding.valueOf("PLAIN"), compressionType,
           Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s5"), TSDataType.valueOf("TEXT"),
+      mmanager.createTimeseries("root.vehicle.d0.s5", TSDataType.valueOf("TEXT"),
           TSEncoding.valueOf("PLAIN"), compressionType,
           Collections.emptyMap());
 
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s0"), TSDataType.valueOf("INT32"),
+      mmanager.createTimeseries("root.vehicle.d1.s0", TSDataType.valueOf("INT32"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s1"), TSDataType.valueOf("INT64"),
+      mmanager.createTimeseries("root.vehicle.d1.s1", TSDataType.valueOf("INT64"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s2"), TSDataType.valueOf("FLOAT"),
+      mmanager.createTimeseries("root.vehicle.d1.s2", TSDataType.valueOf("FLOAT"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s3"), TSDataType.valueOf("DOUBLE"),
+      mmanager.createTimeseries("root.vehicle.d1.s3", TSDataType.valueOf("DOUBLE"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s4"), TSDataType.valueOf("BOOLEAN"),
+      mmanager.createTimeseries("root.vehicle.d1.s4", TSDataType.valueOf("BOOLEAN"),
           TSEncoding.valueOf("PLAIN"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s5"), TSDataType.valueOf("TEXT"),
+      mmanager.createTimeseries("root.vehicle.d1.s5", TSDataType.valueOf("TEXT"),
           TSEncoding.valueOf("PLAIN"), compressionType, Collections.emptyMap());
 
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s0"), TSDataType.valueOf("INT32"),
+      mmanager.createTimeseries("root.vehicle.d2.s0", TSDataType.valueOf("INT32"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s1"), TSDataType.valueOf("INT64"),
+      mmanager.createTimeseries("root.vehicle.d2.s1", TSDataType.valueOf("INT64"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s2"), TSDataType.valueOf("FLOAT"),
+      mmanager.createTimeseries("root.vehicle.d2.s2", TSDataType.valueOf("FLOAT"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s3"), TSDataType.valueOf("DOUBLE"),
+      mmanager.createTimeseries("root.vehicle.d2.s3", TSDataType.valueOf("DOUBLE"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s4"), TSDataType.valueOf("BOOLEAN"),
+      mmanager.createTimeseries("root.vehicle.d2.s4", TSDataType.valueOf("BOOLEAN"),
           TSEncoding.valueOf("PLAIN"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s5"), TSDataType.valueOf("TEXT"),
+      mmanager.createTimeseries("root.vehicle.d2.s5", TSDataType.valueOf("TEXT"),
           TSEncoding.valueOf("PLAIN"), compressionType, Collections.emptyMap());
 
     } catch (Exception e) {
@@ -92,39 +88,4 @@ public class MetadataManagerHelper {
     }
   }
 
-  public static void initMetadata2() {
-
-    mmanager = MManager.getInstance();
-    mmanager.clear();
-    try {
-      mmanager.setStorageGroupToMTree("root.vehicle");
-      CompressionType compressionType =CompressionType.valueOf(TSFileDescriptor.getInstance().getConfig().getCompressor());
-
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s0"), TSDataType.valueOf("INT32"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s1"), TSDataType.valueOf("INT64"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s2"), TSDataType.valueOf("FLOAT"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s3"), TSDataType.valueOf("DOUBLE"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s4"), TSDataType.valueOf("BOOLEAN"), TSEncoding.valueOf("PLAIN"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d0.s5"), TSDataType.valueOf("TEXT"), TSEncoding.valueOf("PLAIN"), compressionType, Collections.emptyMap());
-
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s0"), TSDataType.valueOf("INT32"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s1"), TSDataType.valueOf("INT64"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s2"), TSDataType.valueOf("FLOAT"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s3"), TSDataType.valueOf("DOUBLE"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s4"), TSDataType.valueOf("BOOLEAN"), TSEncoding.valueOf("PLAIN"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d1.s5"), TSDataType.valueOf("TEXT"), TSEncoding.valueOf("PLAIN"), compressionType, Collections.emptyMap());
-
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s0"), TSDataType.valueOf("INT32"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s1"), TSDataType.valueOf("INT64"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s2"), TSDataType.valueOf("FLOAT"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s3"), TSDataType.valueOf("DOUBLE"), TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s4"), TSDataType.valueOf("BOOLEAN"), TSEncoding.valueOf("PLAIN"), compressionType, Collections.emptyMap());
-      mmanager.addPathToMTree(new Path("root.vehicle.d2.s5"), TSDataType.valueOf("TEXT"), TSEncoding.valueOf("PLAIN"), compressionType, Collections.emptyMap());
-
-    } catch (Exception e) {
-
-      throw new RuntimeException("Initialize the metadata manager failed", e);
-    }
-  }
-
 }
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/cache/DeviceMetaDataCacheTest.java b/server/src/test/java/org/apache/iotdb/db/engine/cache/DeviceMetaDataCacheTest.java
index 8aab4ee..ff05387 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/cache/DeviceMetaDataCacheTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/cache/DeviceMetaDataCacheTest.java
@@ -50,8 +50,7 @@ public class DeviceMetaDataCacheTest {
 
   private QueryContext context = EnvironmentUtils.TEST_QUERY_CONTEXT;
 
-  private String storageGroup = "root.vehicle";
-  private String deviceId0 = "root.vehicle.d0";
+  private String storageGroup = "root.vehicle.d0";
   private String measurementId0 = "s0";
   private String measurementId1 = "s1";
   private String measurementId2 = "s2";
@@ -84,7 +83,7 @@ public class DeviceMetaDataCacheTest {
   }
 
   private void insertOneRecord(long time, int num) throws QueryProcessException {
-    TSRecord record = new TSRecord(time, deviceId0);
+    TSRecord record = new TSRecord(time, storageGroup);
     record.addTuple(DataPoint.getDataPoint(TSDataType.INT32, measurementId0, String.valueOf(num)));
     record.addTuple(DataPoint.getDataPoint(TSDataType.INT64, measurementId1, String.valueOf(num)));
     record.addTuple(DataPoint.getDataPoint(TSDataType.FLOAT, measurementId2, String.valueOf(num)));
@@ -126,7 +125,7 @@ public class DeviceMetaDataCacheTest {
   public void test1() throws IOException {
     IoTDBDescriptor.getInstance().getConfig().setMetaDataCacheEnable(false);
     QueryDataSource queryDataSource = storageGroupProcessor
-        .query(deviceId0, measurementId5, context, null, null);
+        .query(storageGroup, measurementId5, context, null, null);
 
     List<TsFileResource> seqResources = queryDataSource.getSeqResources();
     List<TsFileResource> unseqResources = queryDataSource.getUnseqResources();
@@ -140,7 +139,7 @@ public class DeviceMetaDataCacheTest {
     Assert.assertFalse(unseqResources.get(3).isClosed());
 
     List<ChunkMetaData> metaDataList = DeviceMetaDataCache.getInstance()
-        .get(seqResources.get(0), new Path(deviceId0, measurementId5));
+        .get(seqResources.get(0), new Path(storageGroup, measurementId5));
     Assert.assertEquals(0, metaDataList.size());
   }
 
@@ -148,7 +147,7 @@ public class DeviceMetaDataCacheTest {
   public void test2() throws IOException {
     IoTDBDescriptor.getInstance().getConfig().setMetaDataCacheEnable(true);
     QueryDataSource queryDataSource = storageGroupProcessor
-        .query(deviceId0, measurementId5, context, null, null);
+        .query(storageGroup, measurementId5, context, null, null);
 
     List<TsFileResource> seqResources = queryDataSource.getSeqResources();
     List<TsFileResource> unseqResources = queryDataSource.getUnseqResources();
@@ -162,7 +161,7 @@ public class DeviceMetaDataCacheTest {
     Assert.assertFalse(unseqResources.get(3).isClosed());
 
     List<ChunkMetaData> metaDataList = DeviceMetaDataCache.getInstance()
-        .get(seqResources.get(0), new Path(deviceId0, measurementId5));
+        .get(seqResources.get(0), new Path(storageGroup, measurementId5));
     Assert.assertEquals(0, metaDataList.size());
   }
 
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeLogTest.java b/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeLogTest.java
index b554a33..cf4bd93 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeLogTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeLogTest.java
@@ -33,7 +33,7 @@ import org.apache.iotdb.db.engine.merge.manage.MergeResource;
 import org.apache.iotdb.db.engine.merge.task.MergeTask;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
 import org.junit.After;
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeOverLapTest.java b/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeOverLapTest.java
index 4599f8b..a4b5e7c 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeOverLapTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeOverLapTest.java
@@ -28,7 +28,7 @@ import org.apache.iotdb.db.engine.merge.task.MergeTask;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.query.reader.series.SeriesRawDataBatchReader;
 import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeTaskTest.java b/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeTaskTest.java
index 4d698df..e333c66 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeTaskTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeTaskTest.java
@@ -28,7 +28,7 @@ import org.apache.iotdb.db.engine.modification.Deletion;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.query.reader.series.SeriesRawDataBatchReader;
 import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeTest.java b/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeTest.java
index 9d6fe4d..21a4683 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/merge/MergeTest.java
@@ -34,7 +34,7 @@ import org.apache.iotdb.db.engine.cache.TsFileMetaDataCache;
 import org.apache.iotdb.db.engine.merge.manage.MergeManager;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.query.control.FileReaderManager;
@@ -104,10 +104,10 @@ abstract class MergeTest {
     for (int i = 0; i < deviceNum; i++) {
       deviceIds[i] = MERGE_TEST_SG + PATH_SEPARATOR + "device" + i;
     }
-    MManager.getInstance().setStorageGroupToMTree(MERGE_TEST_SG);
+    MManager.getInstance().setStorageGroup(MERGE_TEST_SG);
     for (String device : deviceIds) {
       for (MeasurementSchema measurementSchema : measurementSchemas) {
-        MManager.getInstance().addPathToMTree(
+        MManager.getInstance().createTimeseries(
             device + PATH_SEPARATOR + measurementSchema.getMeasurementId(), measurementSchema
                 .getType(), measurementSchema.getEncodingType(), measurementSchema.getCompressor(),
             Collections.emptyMap());
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionFileNodeTest.java b/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionFileNodeTest.java
index 28da269..5be94ea 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionFileNodeTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionFileNodeTest.java
@@ -39,7 +39,7 @@ import org.apache.iotdb.db.engine.querycontext.ReadOnlyMemChunk;
 import org.apache.iotdb.db.exception.StartupException;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
 import org.apache.iotdb.db.metadata.MManager;
@@ -74,18 +74,17 @@ public class DeletionFileNodeTest {
   }
 
   @Before
-  public void setup() throws MetadataException,
-      PathException, IOException, StorageEngineException, StartupException, StorageGroupException {
+  public void setup() throws MetadataException, StorageEngineException, StartupException {
     EnvironmentUtils.envSetUp();
 
-    MManager.getInstance().setStorageGroupToMTree(processorName);
+    MManager.getInstance().setStorageGroup(processorName);
     for (int i = 0; i < 10; i++) {
-      MManager.getInstance().addPathToMTree(processorName + "." + measurements[i], dataType,
+      MManager.getInstance().createTimeseries(processorName + "." + measurements[i], dataType,
           encoding);
       StorageEngine.getInstance()
           .addTimeSeries(new Path(processorName, measurements[i]), TSDataType.valueOf(dataType),
               TSEncoding.valueOf(encoding),
-              CompressionType.valueOf(TSFileDescriptor.getInstance().getConfig().getCompressor()),
+              TSFileDescriptor.getInstance().getConfig().getCompressor(),
               Collections.emptyMap());
     }
   }
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionQueryTest.java b/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionQueryTest.java
index eb89e08..9e4f16a 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionQueryTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/modification/DeletionQueryTest.java
@@ -30,7 +30,7 @@ import org.apache.iotdb.db.engine.StorageEngine;
 import org.apache.iotdb.db.exception.StartupException;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
 import org.apache.iotdb.db.metadata.MManager;
@@ -70,14 +70,14 @@ public class DeletionQueryTest {
       PathException, IOException, StorageEngineException, StartupException, StorageGroupException {
     EnvironmentUtils.envSetUp();
 
-    MManager.getInstance().setStorageGroupToMTree(processorName);
+    MManager.getInstance().setStorageGroup(processorName);
     for (int i = 0; i < 10; i++) {
-      MManager.getInstance().addPathToMTree(processorName + "." + measurements[i], dataType,
+      MManager.getInstance().createTimeseries(processorName + "." + measurements[i], dataType,
           encoding);
       StorageEngine.getInstance()
           .addTimeSeries(new Path(processorName, measurements[i]), TSDataType.valueOf(dataType),
               TSEncoding.valueOf(encoding),
-              CompressionType.valueOf(TSFileDescriptor.getInstance().getConfig().getCompressor()),
+              TSFileDescriptor.getInstance().getConfig().getCompressor(),
               Collections.emptyMap());
     }
   }
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/FileNodeManagerBenchmark.java b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/FileNodeManagerBenchmark.java
index 3661e5c..7fea61d 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/FileNodeManagerBenchmark.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/FileNodeManagerBenchmark.java
@@ -24,7 +24,7 @@ import java.util.concurrent.atomic.AtomicLong;
 import org.apache.iotdb.db.engine.StorageEngine;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.StorageEngineException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
 import org.apache.iotdb.db.metadata.MManager;
@@ -67,10 +67,10 @@ public class FileNodeManagerBenchmark {
   private static void prepare()
       throws MetadataException, PathException, IOException, StorageGroupException {
     MManager manager = MManager.getInstance();
-    manager.setStorageGroupToMTree(prefix);
+    manager.setStorageGroup(prefix);
     for (String device : devices) {
       for (String measurement : measurements) {
-        manager.addPathToMTree(device + "." + measurement, TSDataType.INT64.toString(),
+        manager.createTimeseries(device + "." + measurement, TSDataType.INT64.toString(),
             TSEncoding.PLAIN.toString());
       }
     }
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessorTest.java b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessorTest.java
index fdf8c23..7617ab5 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessorTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/StorageGroupProcessorTest.java
@@ -25,6 +25,7 @@ import org.apache.iotdb.db.engine.flush.TsFileFlushPolicy;
 import org.apache.iotdb.db.engine.merge.manage.MergeManager;
 import org.apache.iotdb.db.engine.querycontext.QueryDataSource;
 import org.apache.iotdb.db.engine.querycontext.ReadOnlyMemChunk;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.exception.storageGroup.StorageGroupProcessorException;
 import org.apache.iotdb.db.qp.physical.crud.BatchInsertPlan;
@@ -276,7 +277,8 @@ public class StorageGroupProcessorTest {
 
   class DummySGP extends StorageGroupProcessor {
 
-    DummySGP(String systemInfoDir, String storageGroupName) throws StorageGroupProcessorException {
+    DummySGP(String systemInfoDir, String storageGroupName)
+        throws StorageGroupProcessorException, MetadataException {
       super(systemInfoDir, storageGroupName, new TsFileFlushPolicy.DirectFlushPolicy());
     }
 
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TTLTest.java b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TTLTest.java
index 1ec865b..15ce293 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TTLTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TTLTest.java
@@ -20,6 +20,14 @@
 
 package org.apache.iotdb.db.engine.storagegroup;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import org.apache.iotdb.db.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.conf.directories.DirectoryManager;
@@ -28,13 +36,13 @@ import org.apache.iotdb.db.engine.querycontext.QueryDataSource;
 import org.apache.iotdb.db.exception.StartupException;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
 import org.apache.iotdb.db.exception.query.OutOfTTLException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
 import org.apache.iotdb.db.exception.storageGroup.StorageGroupProcessorException;
 import org.apache.iotdb.db.metadata.MManager;
-import org.apache.iotdb.db.metadata.MNode;
+import org.apache.iotdb.db.metadata.mnode.StorageGroupMNode;
 import org.apache.iotdb.db.qp.Planner;
 import org.apache.iotdb.db.qp.executor.PlanExecutor;
 import org.apache.iotdb.db.qp.physical.crud.InsertPlan;
@@ -57,16 +65,6 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
-import java.io.File;
-import java.io.IOException;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
 public class TTLTest {
 
   private String sg1 = "root.TTL_SG1";
@@ -91,35 +89,35 @@ public class TTLTest {
   }
 
   private void createSchemas()
-      throws MetadataException, PathException, StorageGroupProcessorException {
-    MManager.getInstance().setStorageGroupToMTree(sg1);
-    MManager.getInstance().setStorageGroupToMTree(sg2);
+      throws MetadataException, StorageGroupProcessorException {
+    MManager.getInstance().setStorageGroup(sg1);
+    MManager.getInstance().setStorageGroup(sg2);
     storageGroupProcessor = new StorageGroupProcessor(IoTDBDescriptor.getInstance().getConfig()
         .getSystemDir(), sg1, new DirectFlushPolicy());
-    MManager.getInstance().addPathToMTree(g1s1, TSDataType.INT64, TSEncoding.PLAIN,
+    MManager.getInstance().createTimeseries(g1s1, TSDataType.INT64, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, Collections.emptyMap());
     storageGroupProcessor.addMeasurement("s1", TSDataType.INT64, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, Collections.emptyMap());
   }
 
   @Test
-  public void testSetMetaTTL() throws IOException, PathException, StorageGroupException {
+  public void testSetMetaTTL() throws IOException, MetadataException {
     // exception is expected when setting ttl to a non-exist storage group
     boolean caught = false;
     try {
       MManager.getInstance().setTTL(sg1 + ".notExist", ttl);
-    } catch (PathException e) {
+    } catch (MetadataException e) {
       caught = true;
     }
     assertTrue(caught);
 
     // normally set ttl
     MManager.getInstance().setTTL(sg1, ttl);
-    MNode mNode = MManager.getInstance().getNodeByPathWithCheck(sg1);
+    StorageGroupMNode mNode = MManager.getInstance().getStorageGroupNode(sg1);
     assertEquals(ttl, mNode.getDataTTL());
 
     // default ttl
-    mNode = MManager.getInstance().getNodeByPathWithCheck(sg2);
+    mNode = MManager.getInstance().getStorageGroupNode(sg2);
     assertEquals(Long.MAX_VALUE, mNode.getDataTTL());
   }
 
@@ -320,19 +318,19 @@ public class TTLTest {
   @Test
   public void testShowTTL()
       throws IOException, QueryProcessException, QueryFilterOptimizationException,
-      StorageEngineException, MetadataException, SQLException {
+      StorageEngineException, MetadataException {
     MManager.getInstance().setTTL(sg1, ttl);
 
     ShowTTLPlan plan = new ShowTTLPlan(Collections.emptyList());
     PlanExecutor executor = new PlanExecutor();
     QueryDataSet queryDataSet = executor.processQuery(plan, EnvironmentUtils.TEST_QUERY_CONTEXT);
     RowRecord rowRecord = queryDataSet.next();
-    assertEquals(sg2, rowRecord.getFields().get(0).getStringValue());
-    assertEquals("null", rowRecord.getFields().get(1).getStringValue());
-
-    rowRecord = queryDataSet.next();
     assertEquals(sg1, rowRecord.getFields().get(0).getStringValue());
     assertEquals(ttl, rowRecord.getFields().get(1).getLongV());
+
+    rowRecord = queryDataSet.next();
+    assertEquals(sg2, rowRecord.getFields().get(0).getStringValue());
+    assertEquals("null", rowRecord.getFields().get(1).getStringValue());
   }
 
   @Test
diff --git a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorTest.java b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorTest.java
index df1d5e4..1c926d9 100644
--- a/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorTest.java
@@ -34,6 +34,7 @@ import org.apache.iotdb.db.engine.fileSystem.SystemFileFactory;
 import org.apache.iotdb.db.engine.querycontext.ReadOnlyMemChunk;
 import org.apache.iotdb.db.engine.version.SysTimeVersionController;
 import org.apache.iotdb.db.exception.TsFileProcessorException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.qp.physical.crud.InsertPlan;
 import org.apache.iotdb.db.query.context.QueryContext;
@@ -83,7 +84,7 @@ public class TsFileProcessorTest {
   }
 
   @Test
-  public void testWriteAndFlush() throws IOException, QueryProcessException {
+  public void testWriteAndFlush() throws IOException, QueryProcessException, MetadataException {
     logger.info("testWriteAndFlush begin..");
     processor = new TsFileProcessor(storageGroup, SystemFileFactory.INSTANCE.getFile(filePath),
         SchemaUtils.constructSchema(deviceId), SysTimeVersionController.INSTANCE, this::closeTsFileProcessor,
@@ -131,7 +132,8 @@ public class TsFileProcessorTest {
   }
 
   @Test
-  public void testWriteAndRestoreMetadata() throws IOException, QueryProcessException {
+  public void testWriteAndRestoreMetadata()
+      throws IOException, QueryProcessException, MetadataException {
     logger.info("testWriteAndRestoreMetadata begin..");
     processor = new TsFileProcessor(storageGroup, SystemFileFactory.INSTANCE.getFile(filePath),
         SchemaUtils.constructSchema(deviceId), SysTimeVersionController.INSTANCE, this::closeTsFileProcessor,
@@ -202,7 +204,7 @@ public class TsFileProcessorTest {
 
 
   @Test
-  public void testMultiFlush() throws IOException, QueryProcessException {
+  public void testMultiFlush() throws IOException, QueryProcessException, MetadataException {
     logger.info("testWriteAndRestoreMetadata begin..");
     processor = new TsFileProcessor(storageGroup, SystemFileFactory.INSTANCE.getFile(filePath),
         SchemaUtils.constructSchema(deviceId), SysTimeVersionController.INSTANCE, this::closeTsFileProcessor,
@@ -237,7 +239,7 @@ public class TsFileProcessorTest {
 
 
   @Test
-  public void testWriteAndClose() throws IOException, QueryProcessException {
+  public void testWriteAndClose() throws IOException, QueryProcessException, MetadataException {
     logger.info("testWriteAndRestoreMetadata begin..");
     processor = new TsFileProcessor(storageGroup, SystemFileFactory.INSTANCE.getFile(filePath),
         SchemaUtils.constructSchema(deviceId), SysTimeVersionController.INSTANCE,
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBAuthorizationIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBAuthorizationIT.java
index 1406ee6..92f18d9 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBAuthorizationIT.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBAuthorizationIT.java
@@ -435,7 +435,7 @@ public class IoTDBAuthorizationIT {
     // the user cannot delete the timeseries now
     caught = false;
     try {
-      // no privilege to create this one any more
+      // no privilege to delete this one any more
       userStmt.execute("DELETE TIMESERIES root.a.b");
     } catch (SQLException e) {
       caught = true;
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBFlushQueryMergeTest.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBFlushQueryMergeTest.java
index aaa0f44..8a41c63 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBFlushQueryMergeTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBFlushQueryMergeTest.java
@@ -26,7 +26,6 @@ import java.sql.DriverManager;
 import java.sql.ResultSet;
 import java.sql.Statement;
 import java.util.Locale;
-
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.utils.EnvironmentUtils;
 import org.apache.iotdb.jdbc.Config;
@@ -91,10 +90,10 @@ public class IoTDBFlushQueryMergeTest {
     try (Connection connection = DriverManager
         .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
         Statement statement = connection.createStatement()) {
-      boolean hasResultSet = statement.execute("select * from root");
+      boolean hasResultSet = statement.execute("SELECT * FROM root");
       Assert.assertTrue(hasResultSet);
 
-      try (ResultSet resultSet = statement.getResultSet()){
+      try (ResultSet resultSet = statement.getResultSet()) {
         int cnt = 0;
         while (resultSet.next()) {
           cnt++;
@@ -122,14 +121,14 @@ public class IoTDBFlushQueryMergeTest {
 
       for (int i = 1; i <= 3; i++) {
         for (int j = 10; j < 20; j++) {
-          statement.execute(String.format(insertTemplate, i, j, j, j*0.1, String.valueOf(j)));
+          statement.execute(String.format(insertTemplate, i, j, j, j * 0.1, String.valueOf(j)));
         }
       }
       statement.execute("FLUSH");
 
       for (int i = 1; i <= 3; i++) {
         for (int j = 0; j < 10; j++) {
-          statement.execute(String.format(insertTemplate, i, j, j, j*0.1, String.valueOf(j)));
+          statement.execute(String.format(insertTemplate, i, j, j, j * 0.1, String.valueOf(j)));
         }
       }
       statement.execute("FLUSH root.group1");
@@ -137,17 +136,17 @@ public class IoTDBFlushQueryMergeTest {
 
       for (int i = 1; i <= 3; i++) {
         for (int j = 0; j < 30; j++) {
-          statement.execute(String.format(insertTemplate, i, j, j, j*0.1, String.valueOf(j)));
+          statement.execute(String.format(insertTemplate, i, j, j, j * 0.1, String.valueOf(j)));
         }
       }
-      statement.execute("FLUSH root.group1 true");
-      statement.execute("FLUSH root.group2,root.group3 false");
+      statement.execute("FLUSH root.group1 TRUE");
+      statement.execute("FLUSH root.group2,root.group3 FALSE");
 
-      ResultSet resultSet = statement.executeQuery("SELECT * from root.group1,root.group2,root"
+      ResultSet resultSet = statement.executeQuery("SELECT * FROM root.group1,root.group2,root"
           + ".group3");
       int i = 0;
       while (resultSet.next()) {
-        i ++;
+        i++;
       }
       assertEquals(30, i);
 
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBLoadExternalTsfileTest.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBLoadExternalTsfileTest.java
index f4d5a8c..7304028 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBLoadExternalTsfileTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBLoadExternalTsfileTest.java
@@ -18,6 +18,18 @@
  */
 package org.apache.iotdb.db.integration;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
 import org.apache.iotdb.db.engine.StorageEngine;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.StorageEngineException;
@@ -30,13 +42,6 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.sql.*;
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.Assert.*;
-
 public class IoTDBLoadExternalTsfileTest {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(IoTDBLoadExternalTsfileTest.class);
@@ -179,7 +184,8 @@ public class IoTDBLoadExternalTsfileTest {
       List<TsFileResource> resources = new ArrayList<>(
           StorageEngine.getInstance().getProcessor("root.vehicle")
               .getSequenceFileTreeSet());
-      File tmpDir = new File(resources.get(0).getFile().getParentFile().getParentFile().getParentFile(),
+      File tmpDir = new File(
+          resources.get(0).getFile().getParentFile().getParentFile().getParentFile(),
           "tmp" + File.separator + "root.vehicle");
       if (!tmpDir.exists()) {
         tmpDir.mkdirs();
@@ -202,7 +208,8 @@ public class IoTDBLoadExternalTsfileTest {
       }
 
       // load all tsfile in tmp dir
-      tmpDir = new File(resources.get(0).getFile().getParentFile().getParentFile().getParentFile(), "tmp");
+      tmpDir = new File(resources.get(0).getFile().getParentFile().getParentFile().getParentFile(),
+          "tmp");
       statement.execute(String.format("load %s", tmpDir.getAbsolutePath()));
       resources = new ArrayList<>(
           StorageEngine.getInstance().getProcessor("root.vehicle")
@@ -260,7 +267,7 @@ public class IoTDBLoadExternalTsfileTest {
         Statement statement = connection.createStatement()) {
 
       // check query result
-      boolean hasResultSet = statement.execute("select * from root");
+      boolean hasResultSet = statement.execute("SELECT * FROM root");
       Assert.assertTrue(hasResultSet);
       try (ResultSet resultSet = statement.getResultSet()) {
         int cnt = 0;
@@ -330,7 +337,7 @@ public class IoTDBLoadExternalTsfileTest {
       assertEquals(0, new File(tmpDir, "root.test").listFiles().length);
 
       // check query result
-      hasResultSet = statement.execute("select  * from root");
+      hasResultSet = statement.execute("SELECT  * FROM root");
       Assert.assertTrue(hasResultSet);
       try (ResultSet resultSet = statement.getResultSet()) {
         int cnt = 0;
@@ -361,7 +368,8 @@ public class IoTDBLoadExternalTsfileTest {
           StorageEngine.getInstance().getProcessor("root.vehicle")
               .getSequenceFileTreeSet());
 
-      File tmpDir = new File(resources.get(0).getFile().getParentFile().getParentFile().getParentFile(),
+      File tmpDir = new File(
+          resources.get(0).getFile().getParentFile().getParentFile().getParentFile(),
           "tmp" + File.separator + "root.vehicle");
       if (!tmpDir.exists()) {
         tmpDir.mkdirs();
@@ -383,7 +391,7 @@ public class IoTDBLoadExternalTsfileTest {
         statement.execute(String.format("move %s %s", resource.getFile().getPath(), tmpDir));
       }
 
-      boolean hasResultSet = statement.execute("show timeseries");
+      boolean hasResultSet = statement.execute("SHOW timeseries");
       Assert.assertTrue(hasResultSet);
       StringBuilder timeseriesPath = new StringBuilder();
       try (ResultSet resultSet = statement.getResultSet()) {
@@ -435,7 +443,7 @@ public class IoTDBLoadExternalTsfileTest {
               .getSequenceFileTreeSet());
       assertEquals(2, resources.size());
       assertEquals(2, tmpDir.listFiles().length);
-      for(File dir: tmpDir.listFiles()){
+      for (File dir : tmpDir.listFiles()) {
         assertEquals(0, dir.listFiles().length);
       }
     } catch (StorageEngineException e) {
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMetadataFetchIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMetadataFetchIT.java
index 91ecb9e..3eebae1 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMetadataFetchIT.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMetadataFetchIT.java
@@ -87,15 +87,15 @@ public class IoTDBMetadataFetchIT {
           "show timeseries root.a.b", // nonexistent timeseries, thus returning ""
       };
       String[] standards = new String[]{
-          "root.ln.wf01.wt01.status,root.ln.wf01.wt01,BOOLEAN,PLAIN,UNCOMPRESSED,\n",
+          "root.ln.wf01.wt01.status,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,\n",
 
-          "root.ln.wf01.wt01.status,root.ln.wf01.wt01,BOOLEAN,PLAIN,UNCOMPRESSED,\n"
+          "root.ln.wf01.wt01.status,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,\n"
               + "root.ln.wf01.wt01.temperature,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,\n",
 
-          "root.ln.wf01.wt01.status,root.ln.wf01.wt01,BOOLEAN,PLAIN,UNCOMPRESSED,\n"
+          "root.ln.wf01.wt01.status,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,\n"
               + "root.ln.wf01.wt01.temperature,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,\n",
 
-          "root.ln.wf01.wt01.status,root.ln.wf01.wt01,BOOLEAN,PLAIN,UNCOMPRESSED,\n"
+          "root.ln.wf01.wt01.status,root.ln.wf01.wt01,BOOLEAN,PLAIN,SNAPPY,\n"
                   + "root.ln.wf01.wt01.temperature,root.ln.wf01.wt01,FLOAT,RLE,SNAPPY,\n",
 
           "",
@@ -399,7 +399,7 @@ public class IoTDBMetadataFetchIT {
             + "\t\t\t\t\t\t\"args\":\"{}\",\n"
             + "\t\t\t\t\t\t\"StorageGroup\":\"root.ln.wf01.wt01\",\n"
             + "\t\t\t\t\t\t\"DataType\":\"BOOLEAN\",\n"
-            + "\t\t\t\t\t\t\"Compressor\":\"UNCOMPRESSED\",\n"
+            + "\t\t\t\t\t\t\"Compressor\":\"SNAPPY\",\n"
             + "\t\t\t\t\t\t\"Encoding\":\"PLAIN\"\n"
             + "\t\t\t\t\t}\n"
             + "\t\t\t\t}\n"
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMultiSeriesIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMultiSeriesIT.java
index b46989b..debfb9e 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMultiSeriesIT.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBMultiSeriesIT.java
@@ -426,7 +426,7 @@ public class IoTDBMultiSeriesIT {
     } catch (SQLException e) {
       e.printStackTrace();
       assertEquals(
-          "Statement format is not right: Path: [root.vehicle.d0.s10] doesn't correspond to any known time series",
+          "Statement format is not right: Path [root.vehicle.d0.s10] does not exist",
           e.getMessage());
     }
   }
diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBTtlIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBTtlIT.java
index ea9a71d..341627a 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBTtlIT.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBTtlIT.java
@@ -58,12 +58,12 @@ public class IoTDBTtlIT {
       try {
         statement.execute("SET TTL TO root.TTL_SG1 1000");
       } catch (SQLException e) {
-        assertEquals(TSStatusCode.PATH_ERROR.getStatusCode(), e.getErrorCode());
+        assertEquals(TSStatusCode.METADATA_ERROR.getStatusCode(), e.getErrorCode());
       }
       try {
         statement.execute("UNSET TTL TO root.TTL_SG1");
       } catch (SQLException e) {
-        assertEquals(TSStatusCode.PATH_ERROR.getStatusCode(), e.getErrorCode());
+        assertEquals(TSStatusCode.METADATA_ERROR.getStatusCode(), e.getErrorCode());
       }
 
       statement.execute("SET STORAGE GROUP TO root.TTL_SG1");
@@ -71,7 +71,7 @@ public class IoTDBTtlIT {
       try {
         statement.execute("SET TTL TO root.TTL_SG1.s1 1000");
       } catch (SQLException e) {
-        assertEquals(TSStatusCode.NOT_STORAGE_GROUP_ERROR.getStatusCode(), e.getErrorCode());
+        assertEquals(TSStatusCode.METADATA_ERROR.getStatusCode(), e.getErrorCode());
       }
 
       long now = System.currentTimeMillis();
@@ -144,22 +144,22 @@ public class IoTDBTtlIT {
       statement.execute("SET STORAGE GROUP TO root.group2");
 
       String result = doQuery(statement, "SHOW ALL TTL");
-      assertEquals("root.group2,null\n"
-          + "root.group1,null\n", result);
+      assertEquals("root.group1,null\n"
+          + "root.group2,null\n", result);
       result = doQuery(statement, "SHOW TTL ON root.group1");
       assertEquals("root.group1,null\n", result);
 
       statement.execute("SET TTL TO root.group1 10000");
       result = doQuery(statement, "SHOW ALL TTL");
-      assertEquals("root.group2,null\n"
-          + "root.group1,10000\n", result);
+      assertEquals("root.group1,10000\n"
+          + "root.group2,null\n", result);
       result = doQuery(statement, "SHOW TTL ON root.group1");
       assertEquals("root.group1,10000\n", result);
 
       statement.execute("UNSET TTL TO root.group1");
       result = doQuery(statement, "SHOW ALL TTL");
-      assertEquals("root.group2,null\n"
-          + "root.group1,null\n", result);
+      assertEquals("root.group1,null\n"
+          + "root.group2,null\n", result);
       result = doQuery(statement, "SHOW TTL ON root.group1");
       assertEquals("root.group1,null\n", result);
     }
@@ -189,8 +189,8 @@ public class IoTDBTtlIT {
       statement.execute("SET STORAGE GROUP TO root.group2");
 
       String result = doQuery(statement, "SHOW ALL TTL");
-      assertEquals("root.group2,10000\n"
-          + "root.group1,10000\n", result);
+      assertEquals("root.group1,10000\n"
+          + "root.group2,10000\n", result);
     } finally {
       IoTDBDescriptor.getInstance().getConfig().setDefaultTTL(Long.MAX_VALUE);
     }
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MGraphTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/MGraphTest.java
deleted file mode 100644
index cc271e1..0000000
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MGraphTest.java
+++ /dev/null
@@ -1,81 +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.metadata;
-
-import static org.junit.Assert.*;
-
-import org.apache.iotdb.db.exception.path.PathException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
-import org.apache.iotdb.db.utils.EnvironmentUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class MGraphTest {
-
-  @Before
-  public void setUp() throws Exception {
-    EnvironmentUtils.envSetUp();
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    EnvironmentUtils.cleanEnv();
-  }
-
-  @Test
-  public void testCombineMetadataInStrings() {
-    MGraph root = new MGraph("root");
-    MGraph root1 = new MGraph("root");
-    MGraph root2 = new MGraph("root");
-    MGraph root3 = new MGraph("root");
-    try {
-      root.setStorageGroup("root.a.d0");
-      root.addPathToMTree("root.a.d0.s0", "INT32", "RLE");
-      root.addPathToMTree("root.a.d0.s1", "INT32", "RLE");
-
-      root.setStorageGroup("root.a.d1");
-      root.addPathToMTree("root.a.d1.s0", "INT32", "RLE");
-      root.addPathToMTree("root.a.d1.s1", "INT32", "RLE");
-
-      root.setStorageGroup("root.a.b.d0");
-      root.addPathToMTree("root.a.b.d0.s0", "INT32", "RLE");
-
-      root1.setStorageGroup("root.a.d0");
-      root1.addPathToMTree("root.a.d0.s0", "INT32", "RLE");
-      root1.addPathToMTree("root.a.d0.s1", "INT32", "RLE");
-
-      root2.setStorageGroup("root.a.d1");
-      root2.addPathToMTree("root.a.d1.s0", "INT32", "RLE");
-      root2.addPathToMTree("root.a.d1.s1", "INT32", "RLE");
-
-      root3.setStorageGroup("root.a.b.d0");
-      root3.addPathToMTree("root.a.b.d0.s0", "INT32", "RLE");
-
-      String[] metadatas = new String[3];
-      metadatas[0] = root1.toString();
-      metadatas[1] = root2.toString();
-      metadatas[2] = root3.toString();
-      assertEquals(MGraph.combineMetadataInStrings(metadatas), root.toString());
-    } catch (PathException | StorageGroupException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
-    }
-  }
-}
\ No newline at end of file
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MManagerAdvancedTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerAdvancedTest.java
index 2ec2fa9..33962ae 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MManagerAdvancedTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerAdvancedTest.java
@@ -23,10 +23,9 @@ import static org.junit.Assert.fail;
 
 import java.io.IOException;
 import java.util.List;
-import java.util.Map;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
 import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
+import org.apache.iotdb.db.metadata.mnode.MNode;
 import org.apache.iotdb.db.utils.EnvironmentUtils;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.junit.After;
@@ -44,23 +43,23 @@ public class MManagerAdvancedTest {
     EnvironmentUtils.envSetUp();
     mmanager = MManager.getInstance();
 
-    mmanager.setStorageGroupToMTree("root.vehicle.d0");
-    mmanager.setStorageGroupToMTree("root.vehicle.d1");
-    mmanager.setStorageGroupToMTree("root.vehicle.d2");
+    mmanager.setStorageGroup("root.vehicle.d0");
+    mmanager.setStorageGroup("root.vehicle.d1");
+    mmanager.setStorageGroup("root.vehicle.d2");
 
-    mmanager.addPathToMTree("root.vehicle.d0.s0", "INT32", "RLE");
-    mmanager.addPathToMTree("root.vehicle.d0.s1", "INT64", "RLE");
-    mmanager.addPathToMTree("root.vehicle.d0.s2", "FLOAT", "RLE");
-    mmanager.addPathToMTree("root.vehicle.d0.s3", "DOUBLE", "RLE");
-    mmanager.addPathToMTree("root.vehicle.d0.s4", "BOOLEAN", "PLAIN");
-    mmanager.addPathToMTree("root.vehicle.d0.s5", "TEXT", "PLAIN");
+    mmanager.createTimeseries("root.vehicle.d0.s0", "INT32", "RLE");
+    mmanager.createTimeseries("root.vehicle.d0.s1", "INT64", "RLE");
+    mmanager.createTimeseries("root.vehicle.d0.s2", "FLOAT", "RLE");
+    mmanager.createTimeseries("root.vehicle.d0.s3", "DOUBLE", "RLE");
+    mmanager.createTimeseries("root.vehicle.d0.s4", "BOOLEAN", "PLAIN");
+    mmanager.createTimeseries("root.vehicle.d0.s5", "TEXT", "PLAIN");
 
-    mmanager.addPathToMTree("root.vehicle.d1.s0", "INT32", "RLE");
-    mmanager.addPathToMTree("root.vehicle.d1.s1", "INT64", "RLE");
-    mmanager.addPathToMTree("root.vehicle.d1.s2", "FLOAT", "RLE");
-    mmanager.addPathToMTree("root.vehicle.d1.s3", "DOUBLE", "RLE");
-    mmanager.addPathToMTree("root.vehicle.d1.s4", "BOOLEAN", "PLAIN");
-    mmanager.addPathToMTree("root.vehicle.d1.s5", "TEXT", "PLAIN");
+    mmanager.createTimeseries("root.vehicle.d1.s0", "INT32", "RLE");
+    mmanager.createTimeseries("root.vehicle.d1.s1", "INT64", "RLE");
+    mmanager.createTimeseries("root.vehicle.d1.s2", "FLOAT", "RLE");
+    mmanager.createTimeseries("root.vehicle.d1.s3", "DOUBLE", "RLE");
+    mmanager.createTimeseries("root.vehicle.d1.s4", "BOOLEAN", "PLAIN");
+    mmanager.createTimeseries("root.vehicle.d1.s5", "TEXT", "PLAIN");
 
   }
 
@@ -82,37 +81,25 @@ public class MManagerAdvancedTest {
         assertEquals("root.vehicle.d0", fileNames.get(1));
       }
       // test filename by seriesPath
-      assertEquals("root.vehicle.d0", mmanager.getStorageGroupNameByPath("root.vehicle.d0.s1"));
-      Map<String, List<String>> map = mmanager
-          .getAllPathGroupByStorageGroup("root.vehicle.d1.*");
-      assertEquals(1, map.keySet().size());
-      assertEquals(6, map.get("root.vehicle.d1").size());
-      List<String> paths = mmanager.getPaths("root.vehicle.d0");
+      assertEquals("root.vehicle.d0", mmanager.getStorageGroupName("root.vehicle.d0.s1"));
+      List<String> pathList = mmanager.getAllTimeseriesName("root.vehicle.d1.*");
+      assertEquals(6, pathList.size());
+      List<String> paths = mmanager.getAllTimeseriesName("root.vehicle.d0");
       assertEquals(6, paths.size());
-      paths = mmanager.getPaths("root.vehicle.d2");
+      paths = mmanager.getAllTimeseriesName("root.vehicle.d2");
       assertEquals(0, paths.size());
-    } catch (MetadataException | StorageGroupException e) {
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
   }
 
   @Test
-  public void testCache() throws PathException, IOException, StorageGroupException {
-    mmanager.addPathToMTree("root.vehicle.d2.s0", "DOUBLE", "RLE");
-    mmanager.addPathToMTree("root.vehicle.d2.s1", "BOOLEAN", "PLAIN");
-    mmanager.addPathToMTree("root.vehicle.d2.s2.g0", "TEXT", "PLAIN");
-    mmanager.addPathToMTree("root.vehicle.d2.s3", "TEXT", "PLAIN");
-
-    Assert.assertEquals(TSDataType.INT32,
-        mmanager.checkPathStorageGroupAndGetDataType("root.vehicle.d0.s0").getDataType());
-    Assert.assertEquals(TSDataType.INT64,
-        mmanager.checkPathStorageGroupAndGetDataType("root.vehicle.d0.s1").getDataType());
-
-    Assert.assertFalse(
-        mmanager.checkPathStorageGroupAndGetDataType("root.vehicle.d0.s100").isSuccessfully());
-    Assert.assertNull(
-        mmanager.checkPathStorageGroupAndGetDataType("root.vehicle.d0.s100").getDataType());
+  public void testCache() throws MetadataException, IOException, StorageGroupException {
+    mmanager.createTimeseries("root.vehicle.d2.s0", "DOUBLE", "RLE");
+    mmanager.createTimeseries("root.vehicle.d2.s1", "BOOLEAN", "PLAIN");
+    mmanager.createTimeseries("root.vehicle.d2.s2.g0", "TEXT", "PLAIN");
+    mmanager.createTimeseries("root.vehicle.d2.s3", "TEXT", "PLAIN");
 
     MNode node = mmanager.getNodeByPath("root.vehicle.d0");
     Assert.assertEquals(TSDataType.INT32, node.getChild("s0").getSchema().getType());
@@ -120,24 +107,8 @@ public class MManagerAdvancedTest {
     try {
       mmanager.getNodeByPath("root.vehicle.d100");
       fail();
-    } catch (PathException e) {
+    } catch (MetadataException e) {
       // ignore
     }
   }
-
-  @Test
-  public void testGetNextLevelPath()
-      throws PathException, IOException, StorageGroupException {
-    mmanager.addPathToMTree("root.vehicle.d2.s0", "DOUBLE", "RLE");
-    mmanager.addPathToMTree("root.vehicle.d2.s1", "BOOLEAN", "PLAIN");
-    mmanager.addPathToMTree("root.vehicle.d2.s2.g0", "TEXT", "PLAIN");
-    mmanager.addPathToMTree("root.vehicle.d2.s3", "TEXT", "PLAIN");
-
-    List<String> paths = mmanager.getLeafNodePathInNextLevel("root.vehicle.d2");
-    Assert.assertEquals(3, paths.size());
-
-    paths = mmanager.getLeafNodePathInNextLevel("root.vehicle.d2.s2");
-    Assert.assertEquals(1, paths.size());
-  }
-
 }
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java
index e33d058..819e0c5 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerBasicTest.java
@@ -23,18 +23,17 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.util.*;
-
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.utils.EnvironmentUtils;
 import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
-import org.apache.iotdb.tsfile.read.common.Path;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -46,7 +45,7 @@ public class MManagerBasicTest {
 
   @Before
   public void setUp() throws Exception {
-    compressionType = CompressionType.valueOf(TSFileDescriptor.getInstance().getConfig().getCompressor());
+    compressionType = TSFileDescriptor.getInstance().getConfig().getCompressor();
     EnvironmentUtils.envSetUp();
   }
 
@@ -59,203 +58,104 @@ public class MManagerBasicTest {
   public void testAddPathAndExist() {
 
     MManager manager = MManager.getInstance();
-    assertTrue(manager.pathExist("root"));
+    assertTrue(manager.isPathExist("root"));
 
-    assertFalse(manager.pathExist("root.laptop"));
+    assertFalse(manager.isPathExist("root.laptop"));
 
     try {
-      manager.setStorageGroupToMTree("root.laptop.d1");
+      manager.setStorageGroup("root.laptop.d1");
     } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
 
     try {
-      manager.setStorageGroupToMTree("root.laptop");
+      manager.setStorageGroup("root.laptop");
     } catch (MetadataException e) {
-      Assert.assertEquals(
-          "The seriesPath of [root.laptop] already exist, it can't be set to the storage group",
+      Assert.assertEquals("root.laptop has already been set to storage group",
           e.getMessage());
     }
 
     try {
-      manager.addPathToMTree(new Path("root.laptop.d1.s0"), TSDataType.valueOf("INT32"),
+      manager.createTimeseries("root.laptop.d1.s0", TSDataType.valueOf("INT32"),
           TSEncoding.valueOf("RLE"), compressionType, Collections
               .emptyMap());
-    } catch (MetadataException | PathException e) {
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
-    assertTrue(manager.pathExist("root.laptop"));
-    assertTrue(manager.pathExist("root.laptop.d1"));
-    assertTrue(manager.pathExist("root.laptop.d1.s0"));
-    assertFalse(manager.pathExist("root.laptop.d1.s1"));
+    assertTrue(manager.isPathExist("root.laptop"));
+    assertTrue(manager.isPathExist("root.laptop.d1"));
+    assertTrue(manager.isPathExist("root.laptop.d1.s0"));
+    assertFalse(manager.isPathExist("root.laptop.d1.s1"));
     try {
-      manager.addPathToMTree(new Path("root.laptop.d1.s1"), TSDataType.valueOf("INT32"),
+      manager.createTimeseries("root.laptop.d1.s1", TSDataType.valueOf("INT32"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-    } catch (MetadataException | PathException e1) {
+    } catch (MetadataException e1) {
       e1.printStackTrace();
       fail(e1.getMessage());
     }
-    assertTrue(manager.pathExist("root.laptop.d1.s1"));
+    assertTrue(manager.isPathExist("root.laptop.d1.s1"));
     try {
-      manager.deletePaths(Collections.singletonList(new Path("root.laptop.d1.s1")), false);
+      manager.deleteTimeseries("root.laptop.d1.s1");
     } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
     // just delete s0, and don't delete root.laptop.d1??
     // delete storage group or not
-    assertFalse(manager.pathExist("root.laptop.d1.s1"));
+    assertFalse(manager.isPathExist("root.laptop.d1.s1"));
     try {
-      manager.deletePaths(Collections.singletonList(new Path("root.laptop.d1.s0")), false);
+      manager.deleteTimeseries("root.laptop.d1.s0");
     } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
-    assertFalse(manager.pathExist("root.laptop.d1.s0"));
-    assertTrue(manager.pathExist("root.laptop.d1"));
-    assertTrue(manager.pathExist("root.laptop"));
-    assertTrue(manager.pathExist("root"));
+    assertFalse(manager.isPathExist("root.laptop.d1.s0"));
+    assertTrue(manager.isPathExist("root.laptop.d1"));
+    assertTrue(manager.isPathExist("root.laptop"));
+    assertTrue(manager.isPathExist("root"));
 
     try {
-      manager.addPathToMTree(new Path("root.laptop.d1.s1"), TSDataType.valueOf("INT32"),
+      manager.createTimeseries("root.laptop.d1.s1", TSDataType.valueOf("INT32"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-    } catch (MetadataException | PathException e1) {
+    } catch (MetadataException e1) {
       e1.printStackTrace();
       fail(e1.getMessage());
     }
 
     try {
-      manager.addPathToMTree(new Path("root.laptop.d1.s0"), TSDataType.valueOf("INT32"),
+      manager.createTimeseries("root.laptop.d1.s0", TSDataType.valueOf("INT32"),
           TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-    } catch (MetadataException | PathException e1) {
+    } catch (MetadataException e1) {
       e1.printStackTrace();
       fail(e1.getMessage());
     }
 
-    assertFalse(manager.pathExist("root.laptop.d2"));
+    assertFalse(manager.isPathExist("root.laptop.d2"));
     assertFalse(manager.checkStorageGroupByPath("root.laptop.d2"));
 
     try {
-      manager.deletePaths(Collections.singletonList(new Path("root.laptop.d1.s0")), false);
+      manager.deleteTimeseries("root.laptop.d1.s0");
     } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
     try {
-      manager.deletePaths(Collections.singletonList(new Path("root.laptop.d1.s1")), false);
+      manager.deleteTimeseries("root.laptop.d1.s1");
     } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
 
     try {
-      manager.setStorageGroupToMTree("root.laptop.d2");
+      manager.setStorageGroup("root.laptop.d2");
     } catch (MetadataException e) {
       Assert.assertEquals(
           String.format("The seriesPath of %s already exist, it can't be set to the storage group",
               "root.laptop.d2"),
           e.getMessage());
     }
-    /*
-     * check file level
-     */
-    assertFalse(manager.pathExist("root.laptop.d2.s1"));
-    List<Path> paths = new ArrayList<>();
-    paths.add(new Path("root.laptop.d2.s1"));
-    try {
-      manager.checkFileLevel(paths);
-    } catch (StorageGroupException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
-    }
-
-    try {
-      manager.addPathToMTree(new Path("root.laptop.d2.s1"), TSDataType.valueOf("INT32"),
-          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-    } catch (MetadataException | PathException e1) {
-      e1.printStackTrace();
-      fail(e1.getMessage());
-    }
-
-    try {
-      manager.addPathToMTree(new Path("root.laptop.d2.s0"), TSDataType.valueOf("INT32"),
-          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-    } catch (MetadataException | PathException e1) {
-      e1.printStackTrace();
-      fail(e1.getMessage());
-    }
-
-    try {
-      manager.deletePaths(Collections.singletonList(new Path("root.laptop.d2.s0")), false);
-    } catch (MetadataException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
-    }
-    try {
-      manager.deletePaths(Collections.singletonList(new Path("root.laptop.d2.s1")), false);
-    } catch (MetadataException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
-    }
-
-    try {
-      manager.addPathToMTree(new Path("root.laptop.d1.s0"), TSDataType.valueOf("INT32"),
-          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-    } catch (MetadataException | PathException e1) {
-      e1.printStackTrace();
-      fail(e1.getMessage());
-    }
-
-    try {
-      manager.addPathToMTree(new Path("root.laptop.d1.s1"), TSDataType.valueOf("INT32"),
-          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-    } catch (MetadataException | PathException e1) {
-      e1.printStackTrace();
-      fail(e1.getMessage());
-    }
-
-    paths = new ArrayList<>();
-    paths.add(new Path("root.laptop.d1.s0"));
-    try {
-      manager.checkFileLevel(paths);
-    } catch (StorageGroupException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
-    }
-
-    try {
-      manager.addPathToMTree(new Path("root.laptop.d1.s2"), TSDataType.valueOf("INT32"),
-          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-    } catch (MetadataException | PathException e1) {
-      e1.printStackTrace();
-      fail(e1.getMessage());
-    }
-    paths = new ArrayList<>();
-    paths.add(new Path("root.laptop.d1.s2"));
-    try {
-      manager.checkFileLevel(paths);
-    } catch (StorageGroupException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
-    }
-
-    try {
-      manager.addPathToMTree(new Path("root.laptop.d1.s3"), TSDataType.valueOf("INT32"),
-          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
-    } catch (MetadataException | PathException e1) {
-      e1.printStackTrace();
-      fail(e1.getMessage());
-    }
-    paths = new ArrayList<>();
-    paths.add(new Path("root.laptop.d1.s3"));
-    try {
-      manager.checkFileLevel(paths);
-    } catch (StorageGroupException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
-    }
   }
 
   @Test
@@ -264,20 +164,20 @@ public class MManagerBasicTest {
     MManager manager = MManager.getInstance();
 
     try {
-      assertFalse(manager.checkStorageGroupOfMTree("root"));
-      assertFalse(manager.checkStorageGroupOfMTree("root1.laptop.d2"));
-
-      manager.setStorageGroupToMTree("root.laptop.d1");
-      assertTrue(manager.checkStorageGroupOfMTree("root.laptop.d1"));
-      assertFalse(manager.checkStorageGroupOfMTree("root.laptop.d2"));
-      assertFalse(manager.checkStorageGroupOfMTree("root.laptop"));
-      assertFalse(manager.checkStorageGroupOfMTree("root.laptop.d1.s1"));
-
-      manager.setStorageGroupToMTree("root.laptop.d2");
-      assertTrue(manager.checkStorageGroupOfMTree("root.laptop.d1"));
-      assertTrue(manager.checkStorageGroupOfMTree("root.laptop.d2"));
-      assertFalse(manager.checkStorageGroupOfMTree("root.laptop.d3"));
-      assertFalse(manager.checkStorageGroupOfMTree("root.laptop"));
+      assertFalse(manager.isStorageGroup("root"));
+      assertFalse(manager.isStorageGroup("root1.laptop.d2"));
+
+      manager.setStorageGroup("root.laptop.d1");
+      assertTrue(manager.isStorageGroup("root.laptop.d1"));
+      assertFalse(manager.isStorageGroup("root.laptop.d2"));
+      assertFalse(manager.isStorageGroup("root.laptop"));
+      assertFalse(manager.isStorageGroup("root.laptop.d1.s1"));
+
+      manager.setStorageGroup("root.laptop.d2");
+      assertTrue(manager.isStorageGroup("root.laptop.d1"));
+      assertTrue(manager.isStorageGroup("root.laptop.d2"));
+      assertFalse(manager.isStorageGroup("root.laptop.d3"));
+      assertFalse(manager.isStorageGroup("root.laptop"));
     } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
@@ -289,23 +189,23 @@ public class MManagerBasicTest {
 
     MManager manager = MManager.getInstance();
     try {
-      manager.setStorageGroupToMTree("root.laptop.d1");
-      manager.setStorageGroupToMTree("root.laptop.d2");
-      manager.addPathToMTree(new Path("root.laptop.d1.s1"), TSDataType.INT32, TSEncoding.PLAIN,
+      manager.setStorageGroup("root.laptop.d1");
+      manager.setStorageGroup("root.laptop.d2");
+      manager.createTimeseries("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
           CompressionType.GZIP, null);
-      manager.addPathToMTree(new Path("root.laptop.d2.s1"), TSDataType.INT32, TSEncoding.PLAIN,
+      manager.createTimeseries("root.laptop.d2.s1", TSDataType.INT32, TSEncoding.PLAIN,
           CompressionType.GZIP, null);
 
       List<String> list = new ArrayList<>();
 
       list.add("root.laptop.d1");
-      assertEquals(list, manager.getAllStorageGroupNamesByPath("root.laptop.d1.s1"));
-      assertEquals(list, manager.getAllStorageGroupNamesByPath("root.laptop.d1"));
+      assertEquals(list, manager.getStorageGroupByPath("root.laptop.d1.s1"));
+      assertEquals(list, manager.getStorageGroupByPath("root.laptop.d1"));
 
       list.add("root.laptop.d2");
-      assertEquals(list, manager.getAllStorageGroupNamesByPath("root.laptop"));
-      assertEquals(list, manager.getAllStorageGroupNamesByPath("root"));
-    } catch (MetadataException | PathException e) {
+      assertEquals(list, manager.getStorageGroupByPath("root.laptop"));
+      assertEquals(list, manager.getStorageGroupByPath("root"));
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
@@ -316,23 +216,23 @@ public class MManagerBasicTest {
     MManager manager = MManager.getInstance();
 
     try {
-      assertTrue(manager.getAllPathGroupByStorageGroup("root").keySet().isEmpty());
-      assertTrue(manager.getAllStorageGroupNamesByPath("root.vehicle").isEmpty());
-      assertTrue(manager.getAllStorageGroupNamesByPath("root.vehicle.device").isEmpty());
-      assertTrue(manager.getAllStorageGroupNamesByPath("root.vehicle.device.sensor").isEmpty());
-
-      manager.setStorageGroupToMTree("root.vehicle");
-      assertFalse(manager.getAllStorageGroupNamesByPath("root.vehicle").isEmpty());
-      assertFalse(manager.getAllStorageGroupNamesByPath("root.vehicle.device").isEmpty());
-      assertFalse(manager.getAllStorageGroupNamesByPath("root.vehicle.device.sensor").isEmpty());
-      assertTrue(manager.getAllStorageGroupNamesByPath("root.vehicle1").isEmpty());
-      assertTrue(manager.getAllStorageGroupNamesByPath("root.vehicle1.device").isEmpty());
-
-      manager.setStorageGroupToMTree("root.vehicle1.device");
-      assertTrue(manager.getAllStorageGroupNamesByPath("root.vehicle1.device1").isEmpty());
-      assertTrue(manager.getAllStorageGroupNamesByPath("root.vehicle1.device2").isEmpty());
-      assertTrue(manager.getAllStorageGroupNamesByPath("root.vehicle1.device3").isEmpty());
-      assertFalse(manager.getAllStorageGroupNamesByPath("root.vehicle1.device").isEmpty());
+      assertTrue(manager.getAllTimeseriesName("root").isEmpty());
+      assertTrue(manager.getStorageGroupByPath("root.vehicle").isEmpty());
+      assertTrue(manager.getStorageGroupByPath("root.vehicle.device").isEmpty());
+      assertTrue(manager.getStorageGroupByPath("root.vehicle.device.sensor").isEmpty());
+
+      manager.setStorageGroup("root.vehicle");
+      assertFalse(manager.getStorageGroupByPath("root.vehicle").isEmpty());
+      assertFalse(manager.getStorageGroupByPath("root.vehicle.device").isEmpty());
+      assertFalse(manager.getStorageGroupByPath("root.vehicle.device.sensor").isEmpty());
+      assertTrue(manager.getStorageGroupByPath("root.vehicle1").isEmpty());
+      assertTrue(manager.getStorageGroupByPath("root.vehicle1.device").isEmpty());
+
+      manager.setStorageGroup("root.vehicle1.device");
+      assertTrue(manager.getStorageGroupByPath("root.vehicle1.device1").isEmpty());
+      assertTrue(manager.getStorageGroupByPath("root.vehicle1.device2").isEmpty());
+      assertTrue(manager.getStorageGroupByPath("root.vehicle1.device3").isEmpty());
+      assertFalse(manager.getStorageGroupByPath("root.vehicle1.device").isEmpty());
     } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
@@ -343,52 +243,52 @@ public class MManagerBasicTest {
   public void testMaximalSeriesNumberAmongStorageGroup() throws MetadataException, PathException {
     MManager manager = MManager.getInstance();
     assertEquals(0, manager.getMaximalSeriesNumberAmongStorageGroups());
-    manager.setStorageGroupToMTree("root.laptop");
+    manager.setStorageGroup("root.laptop");
     assertEquals(0, manager.getMaximalSeriesNumberAmongStorageGroups());
-    manager.addPathToMTree("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
+    manager.createTimeseries("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
         CompressionType.GZIP, null);
-    manager.addPathToMTree("root.laptop.d1.s2", TSDataType.INT32, TSEncoding.PLAIN,
+    manager.createTimeseries("root.laptop.d1.s2", TSDataType.INT32, TSEncoding.PLAIN,
         CompressionType.GZIP, null);
     assertEquals(2, manager.getMaximalSeriesNumberAmongStorageGroups());
-    manager.setStorageGroupToMTree("root.vehicle");
-    manager.addPathToMTree("root.vehicle.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
+    manager.setStorageGroup("root.vehicle");
+    manager.createTimeseries("root.vehicle.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
         CompressionType.GZIP, null);
     assertEquals(2, manager.getMaximalSeriesNumberAmongStorageGroups());
 
-    manager.deletePaths(Collections.singletonList(new Path("root.laptop.d1.s1")), false);
+    manager.deleteTimeseries("root.laptop.d1.s1");
     assertEquals(1, manager.getMaximalSeriesNumberAmongStorageGroups());
-    manager.deletePaths(Collections.singletonList(new Path("root.laptop.d1.s2")), false);
+    manager.deleteTimeseries("root.laptop.d1.s2");
     assertEquals(1, manager.getMaximalSeriesNumberAmongStorageGroups());
   }
 
   @Test
   public void testGetStorageGroupNameByAutoLevel() {
-    MManager manager = MManager.getInstance();
     int level = IoTDBDescriptor.getInstance().getConfig().getDefaultStorageGroupLevel();
     boolean caughtException;
 
     try {
-      assertEquals("root.laptop", manager.getStorageGroupNameByAutoLevel("root.laptop.d1.s1", level));
-    } catch(PathException e) {
+      assertEquals("root.laptop",
+          MetaUtils.getStorageGroupNameByLevel("root.laptop.d1.s1", level));
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
 
     caughtException = false;
     try {
-      manager.getStorageGroupNameByAutoLevel("root1.laptop.d1.s1", level);
-    } catch(PathException e) {
+      MetaUtils.getStorageGroupNameByLevel("root1.laptop.d1.s1", level);
+    } catch (MetadataException e) {
       caughtException = true;
-      assertEquals("Timeseries [root1.laptop.d1.s1] is not correct. ", e.getMessage());
+      assertEquals("root1.laptop.d1.s1 is not a legal path", e.getMessage());
     }
     assertTrue(caughtException);
 
     caughtException = false;
     try {
-      manager.getStorageGroupNameByAutoLevel("root", level);
-    } catch(PathException e) {
+      MetaUtils.getStorageGroupNameByLevel("root", level);
+    } catch (MetadataException e) {
       caughtException = true;
-      assertEquals("Timeseries [root] is not correct. ", e.getMessage());
+      assertEquals("root is not a legal path", e.getMessage());
     }
     assertTrue(caughtException);
   }
@@ -398,28 +298,25 @@ public class MManagerBasicTest {
     MManager manager = MManager.getInstance();
 
     try {
-      manager.setStorageGroupToMTree("root.laptop");
-      manager.addPathToMTree("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
-              CompressionType.GZIP, null);
-      manager.addPathToMTree("root.laptop.d2.s1", TSDataType.INT32, TSEncoding.PLAIN,
-              CompressionType.GZIP, null);
+      manager.setStorageGroup("root.laptop");
+      manager.createTimeseries("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
+          CompressionType.GZIP, null);
+      manager.createTimeseries("root.laptop.d2.s1", TSDataType.INT32, TSEncoding.PLAIN,
+          CompressionType.GZIP, null);
       List<String> devices = new ArrayList<>();
       devices.add("root.laptop.d1");
       devices.add("root.laptop.d2");
       // usual condition
       assertEquals(devices, manager.getDevices("root.laptop"));
-      manager.setStorageGroupToMTree("root.vehicle");
-      manager.addPathToMTree("root.vehicle.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
-              CompressionType.GZIP, null);
+      manager.setStorageGroup("root.vehicle");
+      manager.createTimeseries("root.vehicle.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
+          CompressionType.GZIP, null);
       devices.add("root.vehicle.d1");
       // prefix with *
       assertEquals(devices, manager.getDevices("root.*"));
     } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
-    } catch (PathException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
     }
   }
 }
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MManagerImproveTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerImproveTest.java
index 91d0d15..bc4cf4a 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MManagerImproveTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerImproveTest.java
@@ -26,12 +26,13 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.iotdb.db.exception.StorageEngineException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
+import org.apache.iotdb.db.metadata.mnode.LeafMNode;
+import org.apache.iotdb.db.metadata.mnode.MNode;
 import org.apache.iotdb.db.utils.EnvironmentUtils;
 import org.apache.iotdb.tsfile.exception.cache.CacheException;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
-import org.apache.iotdb.tsfile.read.common.Path;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -39,6 +40,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class MManagerImproveTest {
+
   private static Logger logger = LoggerFactory.getLogger(MManagerImproveTest.class);
 
   private static final int TIMESERIES_NUM = 1000;
@@ -49,12 +51,12 @@ public class MManagerImproveTest {
   public void setUp() throws Exception {
     EnvironmentUtils.envSetUp();
     mManager = MManager.getInstance();
-    mManager.setStorageGroupToMTree("root.t1.v2");
+    mManager.setStorageGroup("root.t1.v2");
 
     for (int j = 0; j < DEVICE_NUM; j++) {
       for (int i = 0; i < TIMESERIES_NUM; i++) {
         String p = "root.t1.v2.d" + j + ".s" + i;
-        mManager.addPathToMTree(p, "TEXT", "RLE");
+        mManager.createTimeseries(p, "TEXT", "RLE");
       }
     }
 
@@ -69,13 +71,13 @@ public class MManagerImproveTest {
   public void checkSetUp() {
     mManager = MManager.getInstance();
 
-    assertTrue(mManager.pathExist("root.t1.v2.d3.s5"));
-    assertFalse(mManager.pathExist("root.t1.v2.d9.s" + TIMESERIES_NUM));
-    assertFalse(mManager.pathExist("root.t10"));
+    assertTrue(mManager.isPathExist("root.t1.v2.d3.s5"));
+    assertFalse(mManager.isPathExist("root.t1.v2.d9.s" + TIMESERIES_NUM));
+    assertFalse(mManager.isPathExist("root.t10"));
   }
 
   @Test
-  public void analyseTimeCost() throws PathException, StorageGroupException {
+  public void analyseTimeCost() throws MetadataException, StorageGroupException {
     mManager = MManager.getInstance();
 
     long startTime, endTime;
@@ -84,38 +86,18 @@ public class MManagerImproveTest {
 
     String deviceId = "root.t1.v2.d3";
     String measurement = "s5";
-
-    startTime = System.currentTimeMillis();
-    for (int i = 0; i < 100000; i++) {
-      String path = deviceId + "." + measurement;
-    }
-    endTime = System.currentTimeMillis();
-    string_combine += endTime - startTime;
     String path = deviceId + "." + measurement;
 
     startTime = System.currentTimeMillis();
     for (int i = 0; i < 100000; i++) {
-      assertTrue(mManager.pathExist(path));
+      assertTrue(mManager.isPathExist(path));
     }
     endTime = System.currentTimeMillis();
     path_exist += endTime - startTime;
 
     startTime = System.currentTimeMillis();
-    for (int i = 0; i < 100000; i++) {
-      List<Path> paths = new ArrayList<>();
-      paths.add(new Path(path));
-    }
     endTime = System.currentTimeMillis();
     list_init += endTime - startTime;
-    List<Path> paths = new ArrayList<>();
-    paths.add(new Path(path));
-
-    startTime = System.currentTimeMillis();
-    for (int i = 0; i < 100000; i++) {
-      assertTrue(mManager.checkFileLevel(paths));
-    }
-    endTime = System.currentTimeMillis();
-    check_filelevel += endTime - startTime;
 
     startTime = System.currentTimeMillis();
     for (int i = 0; i < 100000; i++) {
@@ -133,100 +115,38 @@ public class MManagerImproveTest {
   }
 
   private void doOriginTest(String deviceId, List<String> measurementList)
-      throws PathException, StorageGroupException {
+      throws MetadataException, StorageGroupException {
     for (String measurement : measurementList) {
       String path = deviceId + "." + measurement;
-      assertTrue(mManager.pathExist(path));
-      List<Path> paths = new ArrayList<>();
-      paths.add(new Path(path));
-      assertTrue(mManager.checkFileLevel(paths));
+      assertTrue(mManager.isPathExist(path));
       TSDataType dataType = mManager.getSeriesType(path);
       assertEquals(TSDataType.TEXT, dataType);
     }
   }
 
   private void doPathLoopOnceTest(String deviceId, List<String> measurementList)
-      throws PathException, StorageGroupException {
+      throws MetadataException, StorageGroupException {
     for (String measurement : measurementList) {
       String path = deviceId + "." + measurement;
-      List<Path> paths = new ArrayList<>();
-      paths.add(new Path(path));
-      assertTrue(mManager.checkFileLevel(paths));
-      TSDataType dataType = mManager.getSeriesTypeWithCheck(path);
-      assertEquals(TSDataType.TEXT, dataType);
-    }
-  }
-
-  private void doDealdeviceIdOnceTest(String deviceId, List<String> measurementList)
-      throws PathException, StorageGroupException {
-    boolean isFileLevelChecked;
-    List<Path> tempList = new ArrayList<>();
-    tempList.add(new Path(deviceId));
-    try {
-      isFileLevelChecked = mManager.checkFileLevel(tempList);
-    } catch (StorageGroupException e) {
-      isFileLevelChecked = false;
-    }
-    MNode node = mManager.getNodeByPath(deviceId);
-
-    for (String measurement : measurementList) {
-      assertTrue(mManager.pathExist(node, measurement));
-      List<Path> paths = new ArrayList<>();
-      paths.add(new Path(measurement));
-      if (!isFileLevelChecked) {
-        isFileLevelChecked = mManager.checkFileLevel(node, paths);
-      }
-      assertTrue(isFileLevelChecked);
-      TSDataType dataType = mManager.getSeriesType(node, measurement);
-      assertEquals(TSDataType.TEXT, dataType);
-    }
-  }
-
-  private void doRemoveListTest(String deviceId, List<String> measurementList)
-      throws PathException, StorageGroupException {
-    for (String measurement : measurementList) {
-      String path = deviceId + "." + measurement;
-      assertTrue(mManager.pathExist(path));
-      assertTrue(mManager.checkFileLevel(path));
       TSDataType dataType = mManager.getSeriesType(path);
       assertEquals(TSDataType.TEXT, dataType);
     }
   }
 
-  private void doAllImproveTest(String deviceId, List<String> measurementList)
-      throws PathException, StorageGroupException {
-    boolean isFileLevelChecked;
-    try {
-      isFileLevelChecked = mManager.checkFileLevel(deviceId);
-    } catch (StorageGroupException e) {
-      isFileLevelChecked = false;
-    }
-    MNode node = mManager.getNodeByPathWithCheck(deviceId);
-
-    for (String measurement : measurementList) {
-      if (!isFileLevelChecked) {
-        isFileLevelChecked = mManager.checkFileLevelWithCheck(node, measurement);
-      }
-      assertTrue(isFileLevelChecked);
-      TSDataType dataType = mManager.getSeriesTypeWithCheck(node, measurement);
-      assertEquals(TSDataType.TEXT, dataType);
-    }
-  }
-
   private void doCacheTest(String deviceId, List<String> measurementList)
-      throws CacheException, PathException {
-    MNode node = mManager.getNodeByPathFromCache(deviceId);
+      throws MetadataException {
+    MNode node = mManager.getDeviceNodeWithAutoCreateStorageGroup(deviceId);
     for (String s : measurementList) {
       assertTrue(node.hasChild(s));
       MNode measurementNode = node.getChild(s);
-      assertTrue(measurementNode.isLeaf());
+      assertTrue(measurementNode instanceof LeafMNode);
       TSDataType dataType = measurementNode.getSchema().getType();
       assertEquals(TSDataType.TEXT, dataType);
     }
   }
 
   @Test
-  public void improveTest() throws PathException, StorageGroupException, CacheException {
+  public void improveTest() throws MetadataException, StorageGroupException, CacheException {
     mManager = MManager.getInstance();
 
     long startTime, endTime;
@@ -255,27 +175,6 @@ public class MManagerImproveTest {
 
     startTime = System.currentTimeMillis();
     for (String deviceId : deviceIdList) {
-      doDealdeviceIdOnceTest(deviceId, measurementList);
-    }
-    endTime = System.currentTimeMillis();
-    logger.debug("deal deviceId once:\t" + (endTime - startTime));
-
-    startTime = System.currentTimeMillis();
-    for (String deviceId : deviceIdList) {
-      doRemoveListTest(deviceId, measurementList);
-    }
-    endTime = System.currentTimeMillis();
-    logger.debug("remove list:\t" + (endTime - startTime));
-
-    startTime = System.currentTimeMillis();
-    for (String deviceId : deviceIdList) {
-      doAllImproveTest(deviceId, measurementList);
-    }
-    endTime = System.currentTimeMillis();
-    logger.debug("improve all:\t" + (endTime - startTime));
-
-    startTime = System.currentTimeMillis();
-    for (String deviceId : deviceIdList) {
       doCacheTest(deviceId, measurementList);
     }
     endTime = System.currentTimeMillis();
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
index e5f40f9..b62dc50 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MTreeTest.java
@@ -26,9 +26,7 @@ import static org.junit.Assert.fail;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
-import org.apache.iotdb.db.exception.path.PathException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
+import org.apache.iotdb.db.exception.metadata.MetadataException;
 import org.apache.iotdb.db.utils.EnvironmentUtils;
 import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
@@ -52,96 +50,87 @@ public class MTreeTest {
   }
 
   @Test
-  public void testAddLeftNodePath() {
-    MTree root = new MTree("root");
+  public void testAddLeftNodePath() throws MetadataException {
+    MTree root = new MTree();
+    root.setStorageGroup("root.laptop");
     try {
-      root.addTimeseriesPath("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-    } catch (PathException e) {
+      root.createTimeseries("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
     try {
-      root.addTimeseriesPath("root.laptop.d1.s1.b", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-    } catch (PathException e) {
+      root.createTimeseries("root.laptop.d1.s1.b", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
+    } catch (MetadataException e) {
       Assert.assertEquals(
-          String.format("Timeseries [%s] can't be created. node [%s] is left node",
-              "root.laptop.d1.s1.b", "s1"), e.getMessage());
+          String.format("Path [%s] already exist", "root.laptop.d1.s1", "s1"), e.getMessage());
     }
   }
 
   @Test
-  public void testAddAndPathExist() {
-    MTree root = new MTree("root");
+  public void testAddAndPathExist() throws MetadataException {
+    MTree root = new MTree();
     String path1 = "root";
+    root.setStorageGroup("root.laptop");
     assertTrue(root.isPathExist(path1));
     assertFalse(root.isPathExist("root.laptop.d1"));
     try {
-      root.addTimeseriesPath("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-    } catch (PathException e1) {
+      root.createTimeseries("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
+    } catch (MetadataException e1) {
       fail(e1.getMessage());
     }
     assertTrue(root.isPathExist("root.laptop.d1"));
     assertTrue(root.isPathExist("root.laptop"));
     assertFalse(root.isPathExist("root.laptop.d1.s2"));
     try {
-      root.addTimeseriesPath("aa.bb.cc", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
-          (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-    } catch (PathException e) {
-      Assert.assertEquals(String.format("Timeseries [%s] is not correct. ", "aa.bb.cc"), e.getMessage());
+      root.createTimeseries("aa.bb.cc", TSDataType.INT32, TSEncoding.RLE,
+          TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
+    } catch (MetadataException e) {
+      Assert.assertEquals(String.format("%s is not a legal path", "aa.bb.cc"),
+          e.getMessage());
     }
   }
 
   @Test
   public void testAddAndQueryPath() {
-    MTree root = new MTree("root");
+    MTree root = new MTree();
     try {
       assertFalse(root.isPathExist("root.a.d0"));
-      assertFalse(root.checkFileNameByPath("root.a.d0"));
+      assertFalse(root.checkStorageGroupByPath("root.a.d0"));
       root.setStorageGroup("root.a.d0");
-      root.addTimeseriesPath("root.a.d0.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-      root.addTimeseriesPath("root.a.d0.s1", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
+      root.createTimeseries("root.a.d0.s0", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
+      root.createTimeseries("root.a.d0.s1", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
 
       assertFalse(root.isPathExist("root.a.d1"));
-      assertFalse(root.checkFileNameByPath("root.a.d1"));
+      assertFalse(root.checkStorageGroupByPath("root.a.d1"));
       root.setStorageGroup("root.a.d1");
-      root.addTimeseriesPath("root.a.d1.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-      root.addTimeseriesPath("root.a.d1.s1", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
+      root.createTimeseries("root.a.d1.s0", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
+      root.createTimeseries("root.a.d1.s1", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
 
       root.setStorageGroup("root.a.b.d0");
-      root.addTimeseriesPath("root.a.b.d0.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
+      root.createTimeseries("root.a.b.d0.s0", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
 
-    } catch (PathException | StorageGroupException e1) {
+    } catch (MetadataException e1) {
       e1.printStackTrace();
     }
 
     try {
-      Map<String, List<String>> result = root.getAllPath("root.a.*.s0");
+      List<String> result = root.getAllTimeseriesName("root.a.*.s0");
       assertEquals(2, result.size());
-      assertTrue(result.containsKey("root.a.d1"));
-      assertEquals("root.a.d1.s0", result.get("root.a.d1").get(0));
-      assertTrue(result.containsKey("root.a.d0"));
-      assertEquals("root.a.d0.s0", result.get("root.a.d0").get(0));
-
-      result = root.getAllPath("root.a.*.*.s0");
-      assertTrue(result.containsKey("root.a.b.d0"));
-      assertEquals("root.a.b.d0.s0", result.get("root.a.b.d0").get(0));
-    } catch (PathException e) {
+      assertEquals("root.a.d0.s0", result.get(0));
+      assertEquals("root.a.d1.s0", result.get(1));
+
+      result = root.getAllTimeseriesName("root.a.*.*.s0");
+      assertEquals("root.a.b.d0.s0", result.get(0));
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
@@ -150,59 +139,51 @@ public class MTreeTest {
 
   @Test
   public void testCombineMetadataInStrings() {
-    MTree root = new MTree("root");
-    MTree root1 = new MTree("root");
-    MTree root2 = new MTree("root");
-    MTree root3 = new MTree("root");
+    MTree root = new MTree();
+    MTree root1 = new MTree();
+    MTree root2 = new MTree();
+    MTree root3 = new MTree();
     try {
+      CompressionType compressionType = TSFileDescriptor.getInstance().getConfig().getCompressor();
+
       root.setStorageGroup("root.a.d0");
-      root.addTimeseriesPath("root.a.d0.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-      root.addTimeseriesPath("root.a.d0.s1", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
+      root.createTimeseries("root.a.d0.s0", TSDataType.valueOf("INT32"),
+          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
+      root.createTimeseries("root.a.d0.s1", TSDataType.valueOf("INT32"),
+          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
 
       root.setStorageGroup("root.a.d1");
-      root.addTimeseriesPath("root.a.d1.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-      root.addTimeseriesPath("root.a.d1.s1", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
+      root.createTimeseries("root.a.d1.s0", TSDataType.valueOf("INT32"),
+          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
+      root.createTimeseries("root.a.d1.s1", TSDataType.valueOf("INT32"),
+          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
 
       root.setStorageGroup("root.a.b.d0");
-      root.addTimeseriesPath("root.a.b.d0.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
+      root.createTimeseries("root.a.b.d0.s0", TSDataType.valueOf("INT32"),
+          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
 
       root1.setStorageGroup("root.a.d0");
-      root1.addTimeseriesPath("root.a.d0.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-      root1.addTimeseriesPath("root.a.d0.s1", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
+      root1.createTimeseries("root.a.d0.s0", TSDataType.valueOf("INT32"),
+          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
+      root1.createTimeseries("root.a.d0.s1", TSDataType.valueOf("INT32"),
+          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
 
       root2.setStorageGroup("root.a.d1");
-      root2.addTimeseriesPath("root.a.d1.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-      root2.addTimeseriesPath("root.a.d1.s1", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
+      root2.createTimeseries("root.a.d1.s0", TSDataType.valueOf("INT32"),
+          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
+      root2.createTimeseries("root.a.d1.s1", TSDataType.valueOf("INT32"),
+          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
 
       root3.setStorageGroup("root.a.b.d0");
-      root3.addTimeseriesPath("root.a.b.d0.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-
-      String[] metadataStrs = new String[3];
-      metadataStrs[0] = root1.toString();
-      metadataStrs[1] = root2.toString();
-      metadataStrs[2] = root3.toString();
-      assertEquals(MTree.combineMetadataInStrings(metadataStrs), root.toString());
-    } catch (PathException | StorageGroupException e) {
+      root3.createTimeseries("root.a.b.d0.s0", TSDataType.valueOf("INT32"),
+          TSEncoding.valueOf("RLE"), compressionType, Collections.emptyMap());
+
+      String[] metadatas = new String[3];
+      metadatas[0] = root1.toString();
+      metadatas[1] = root2.toString();
+      metadatas[2] = root3.toString();
+      assertEquals(MTree.combineMetadataInStrings(metadatas), root.toString());
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
@@ -211,29 +192,29 @@ public class MTreeTest {
   @Test
   public void testSetStorageGroup() {
     // set storage group first
-    MTree root = new MTree("root");
+    MTree root = new MTree();
     try {
       root.setStorageGroup("root.laptop.d1");
       assertTrue(root.isPathExist("root.laptop.d1"));
-      assertTrue(root.checkFileNameByPath("root.laptop.d1"));
-      assertEquals("root.laptop.d1", root.getStorageGroupNameByPath("root.laptop.d1"));
+      assertTrue(root.checkStorageGroupByPath("root.laptop.d1"));
+      assertEquals("root.laptop.d1", root.getStorageGroupName("root.laptop.d1"));
       assertFalse(root.isPathExist("root.laptop.d1.s1"));
-      assertTrue(root.checkFileNameByPath("root.laptop.d1.s1"));
-      assertEquals("root.laptop.d1", root.getStorageGroupNameByPath("root.laptop.d1.s1"));
-    } catch (StorageGroupException e) {
+      assertTrue(root.checkStorageGroupByPath("root.laptop.d1.s1"));
+      assertEquals("root.laptop.d1", root.getStorageGroupName("root.laptop.d1.s1"));
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
     try {
       root.setStorageGroup("root.laptop.d2");
-    } catch (StorageGroupException e) {
+    } catch (MetadataException e) {
       fail(e.getMessage());
     }
     try {
       root.setStorageGroup("root.laptop");
-    } catch (StorageGroupException e) {
+    } catch (MetadataException e) {
       Assert.assertEquals(
-          "The seriesPath of [root.laptop] already exist, it can't be set to the storage group",
+          "root.laptop has already been set to storage group",
           e.getMessage());
     }
     // check timeseries
@@ -243,36 +224,32 @@ public class MTreeTest {
     assertFalse(root.isPathExist("root.laptop.d2.s1"));
 
     try {
-      assertEquals("root.laptop.d1", root.getStorageGroupNameByPath("root.laptop.d1.s0"));
-      root.addTimeseriesPath("root.laptop.d1.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-      assertEquals("root.laptop.d1", root.getStorageGroupNameByPath("root.laptop.d1.s1"));
-      root.addTimeseriesPath("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-      assertEquals("root.laptop.d2", root.getStorageGroupNameByPath("root.laptop.d2.s0"));
-      root.addTimeseriesPath("root.laptop.d2.s0", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-      assertEquals("root.laptop.d2", root.getStorageGroupNameByPath("root.laptop.d2.s1"));
-      root.addTimeseriesPath("root.laptop.d2.s1", TSDataType.INT32, TSEncoding.RLE,
-          CompressionType.valueOf
-              (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
-    } catch (PathException | StorageGroupException e) {
+      assertEquals("root.laptop.d1", root.getStorageGroupName("root.laptop.d1.s0"));
+      root.createTimeseries("root.laptop.d1.s0", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
+      assertEquals("root.laptop.d1", root.getStorageGroupName("root.laptop.d1.s1"));
+      root.createTimeseries("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
+      assertEquals("root.laptop.d2", root.getStorageGroupName("root.laptop.d2.s0"));
+      root.createTimeseries("root.laptop.d2.s0", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
+      assertEquals("root.laptop.d2", root.getStorageGroupName("root.laptop.d2.s1"));
+      root.createTimeseries("root.laptop.d2.s1", TSDataType.INT32, TSEncoding.RLE,
+              TSFileDescriptor.getInstance().getConfig().getCompressor(), Collections.EMPTY_MAP);
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
     try {
-      root.deletePath("root.laptop.d1.s0");
-    } catch (PathException e) {
+      root.deleteTimeseriesAndReturnEmptyStorageGroup("root.laptop.d1.s0");
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
     assertFalse(root.isPathExist("root.laptop.d1.s0"));
     try {
-      root.deletePath("root.laptop.d1");
-    } catch (PathException e) {
+      root.deleteStorageGroup("root.laptop.d1");
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
@@ -286,22 +263,22 @@ public class MTreeTest {
   @Test
   public void testCheckStorageGroup() {
     // set storage group first
-    MTree root = new MTree("root");
+    MTree root = new MTree();
     try {
-      assertFalse(root.checkStorageGroup("root"));
-      assertFalse(root.checkStorageGroup("root1.laptop.d2"));
+      assertFalse(root.isStorageGroup("root"));
+      assertFalse(root.isStorageGroup("root1.laptop.d2"));
 
       root.setStorageGroup("root.laptop.d1");
-      assertTrue(root.checkStorageGroup("root.laptop.d1"));
-      assertFalse(root.checkStorageGroup("root.laptop.d2"));
-      assertFalse(root.checkStorageGroup("root.laptop"));
-      assertFalse(root.checkStorageGroup("root.laptop.d1.s1"));
+      assertTrue(root.isStorageGroup("root.laptop.d1"));
+      assertFalse(root.isStorageGroup("root.laptop.d2"));
+      assertFalse(root.isStorageGroup("root.laptop"));
+      assertFalse(root.isStorageGroup("root.laptop.d1.s1"));
 
       root.setStorageGroup("root.laptop.d2");
-      assertTrue(root.checkStorageGroup("root.laptop.d1"));
-      assertTrue(root.checkStorageGroup("root.laptop.d2"));
-      assertFalse(root.checkStorageGroup("root.laptop.d3"));
-    } catch (StorageGroupException e) {
+      assertTrue(root.isStorageGroup("root.laptop.d1"));
+      assertTrue(root.isStorageGroup("root.laptop.d2"));
+      assertFalse(root.isStorageGroup("root.laptop.d3"));
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
@@ -310,25 +287,25 @@ public class MTreeTest {
   @Test
   public void testGetAllFileNamesByPath() {
     // set storage group first
-    MTree root = new MTree("root");
+    MTree root = new MTree();
     try {
       root.setStorageGroup("root.laptop.d1");
       root.setStorageGroup("root.laptop.d2");
-      root.addTimeseriesPath("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
+      root.createTimeseries("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
           CompressionType.GZIP, null);
-      root.addTimeseriesPath("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
+      root.createTimeseries("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN,
           CompressionType.GZIP, null);
 
       List<String> list = new ArrayList<>();
 
       list.add("root.laptop.d1");
-      assertEquals(list, root.getAllFileNamesByPath("root.laptop.d1.s1"));
-      assertEquals(list, root.getAllFileNamesByPath("root.laptop.d1"));
+      assertEquals(list, root.getStorageGroupByPath("root.laptop.d1.s1"));
+      assertEquals(list, root.getStorageGroupByPath("root.laptop.d1"));
 
       list.add("root.laptop.d2");
-      assertEquals(list, root.getAllFileNamesByPath("root.laptop"));
-      assertEquals(list, root.getAllFileNamesByPath("root"));
-    } catch (PathException | StorageGroupException e) {
+      assertEquals(list, root.getStorageGroupByPath("root.laptop"));
+      assertEquals(list, root.getStorageGroupByPath("root"));
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
@@ -337,26 +314,26 @@ public class MTreeTest {
   @Test
   public void testCheckStorageExistOfPath() {
     // set storage group first
-    MTree root = new MTree("root");
+    MTree root = new MTree();
     try {
-      assertTrue(root.getAllFileNamesByPath("root").isEmpty());
-      assertTrue(root.getAllFileNamesByPath("root.vehicle").isEmpty());
-      assertTrue(root.getAllFileNamesByPath("root.vehicle.device").isEmpty());
-      assertTrue(root.getAllFileNamesByPath("root.vehicle.device.sensor").isEmpty());
+      assertTrue(root.getStorageGroupByPath("root").isEmpty());
+      assertTrue(root.getStorageGroupByPath("root.vehicle").isEmpty());
+      assertTrue(root.getStorageGroupByPath("root.vehicle.device").isEmpty());
+      assertTrue(root.getStorageGroupByPath("root.vehicle.device.sensor").isEmpty());
 
       root.setStorageGroup("root.vehicle");
-      assertFalse(root.getAllFileNamesByPath("root.vehicle").isEmpty());
-      assertFalse(root.getAllFileNamesByPath("root.vehicle.device").isEmpty());
-      assertFalse(root.getAllFileNamesByPath("root.vehicle.device.sensor").isEmpty());
-      assertTrue(root.getAllFileNamesByPath("root.vehicle1").isEmpty());
-      assertTrue(root.getAllFileNamesByPath("root.vehicle1.device").isEmpty());
+      assertFalse(root.getStorageGroupByPath("root.vehicle").isEmpty());
+      assertFalse(root.getStorageGroupByPath("root.vehicle.device").isEmpty());
+      assertFalse(root.getStorageGroupByPath("root.vehicle.device.sensor").isEmpty());
+      assertTrue(root.getStorageGroupByPath("root.vehicle1").isEmpty());
+      assertTrue(root.getStorageGroupByPath("root.vehicle1.device").isEmpty());
 
       root.setStorageGroup("root.vehicle1.device");
-      assertTrue(root.getAllFileNamesByPath("root.vehicle1.device1").isEmpty());
-      assertTrue(root.getAllFileNamesByPath("root.vehicle1.device2").isEmpty());
-      assertTrue(root.getAllFileNamesByPath("root.vehicle1.device3").isEmpty());
-      assertFalse(root.getAllFileNamesByPath("root.vehicle1.device").isEmpty());
-    } catch (PathException | StorageGroupException e) {
+      assertTrue(root.getStorageGroupByPath("root.vehicle1.device1").isEmpty());
+      assertTrue(root.getStorageGroupByPath("root.vehicle1.device2").isEmpty());
+      assertTrue(root.getStorageGroupByPath("root.vehicle1.device3").isEmpty());
+      assertFalse(root.getStorageGroupByPath("root.vehicle1.device").isEmpty());
+    } catch (MetadataException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/MetadataTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/MetadataTest.java
deleted file mode 100644
index 5c67d4b..0000000
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MetadataTest.java
+++ /dev/null
@@ -1,88 +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.metadata;
-
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
-import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
-import org.apache.iotdb.db.utils.EnvironmentUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class MetadataTest {
-
-  @Before
-  public void setUp() throws Exception {
-    EnvironmentUtils.envSetUp();
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    EnvironmentUtils.cleanEnv();
-  }
-
-  @Test
-  public void testCombineMetadatas() {
-    MManager manager = MManager.getInstance();
-
-    try {
-      manager.setStorageGroupToMTree("root.t.d1");
-      manager.addPathToMTree("root.t.d1.s0", "INT32", "RLE");
-      manager.addPathToMTree("root.t.d1.s1", "DOUBLE", "RLE");
-      manager.setStorageGroupToMTree("root.t.d2");
-      manager.addPathToMTree("root.t.d2.s1", "DOUBLE", "RLE");
-      Metadata metadata1 = manager.getMetadata();
-
-      manager.clear();
-
-      manager.setStorageGroupToMTree("root.t.d3");
-      manager.addPathToMTree("root.t.d3.s1", "DOUBLE", "RLE");
-      manager.addPathToMTree("root.t.d3.s2", "TEXT", "RLE");
-      manager.setStorageGroupToMTree("root.t1.d1");
-      manager.addPathToMTree("root.t1.d1.s1", "DOUBLE", "RLE");
-      manager.addPathToMTree("root.t1.d1.s2", "TEXT", "RLE");
-      Metadata metadata2 = manager.getMetadata();
-
-      manager.clear();
-
-      manager.setStorageGroupToMTree("root.t.d1");
-      manager.addPathToMTree("root.t.d1.s0", "INT32", "RLE");
-      manager.addPathToMTree("root.t.d1.s1", "DOUBLE", "RLE");
-      manager.setStorageGroupToMTree("root.t.d2");
-      manager.addPathToMTree("root.t.d2.s1", "DOUBLE", "RLE");
-      manager.setStorageGroupToMTree("root.t.d3");
-      manager.addPathToMTree("root.t.d3.s1", "DOUBLE", "RLE");
-      manager.addPathToMTree("root.t.d3.s2", "TEXT", "RLE");
-      manager.setStorageGroupToMTree("root.t1.d1");
-      manager.addPathToMTree("root.t1.d1.s1", "DOUBLE", "RLE");
-      manager.addPathToMTree("root.t1.d1.s2", "TEXT", "RLE");
-      Metadata metadata = manager.getMetadata();
-
-      Metadata combineMetadata = Metadata.combineMetadatas(new Metadata[]{metadata1, metadata2});
-      assertTrue(metadata.equals(combineMetadata));
-    } catch (PathException | IOException | MetadataException | StorageGroupException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
-    }
-  }
-}
\ No newline at end of file
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/PlannerTest.java b/server/src/test/java/org/apache/iotdb/db/qp/PlannerTest.java
index bc0159a..dd1d6c0 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/PlannerTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/PlannerTest.java
@@ -38,8 +38,8 @@ import static org.junit.Assert.assertEquals;
 
 public class PlannerTest {
 
-  private CompressionType compressionType = CompressionType.valueOf(
-      TSFileDescriptor.getInstance().getConfig().getCompressor());
+  private CompressionType compressionType =
+      TSFileDescriptor.getInstance().getConfig().getCompressor();
   private MManager mManager = MManager.getInstance();
   private Planner processor = new Planner();
 
@@ -50,42 +50,42 @@ public class PlannerTest {
   @Before
   public void setUp() throws Exception {
     EnvironmentUtils.envSetUp();
-    mManager.setStorageGroupToMTree("root.vehicle");
-    mManager.setStorageGroupToMTree("root.vehicle1");
-    mManager.addPathToMTree("root.vehicle.device1.sensor1", TSDataType.valueOf("INT32"),
+    mManager.setStorageGroup("root.vehicle");
+    mManager.setStorageGroup("root.vehicle1");
+    mManager.createTimeseries("root.vehicle.device1.sensor1", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle.device1.sensor2", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle.device1.sensor2", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle.device1.sensor3", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle.device1.sensor3", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle.device2.sensor1", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle.device2.sensor1", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle.device2.sensor2", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle.device2.sensor2", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle.device2.sensor3", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle.device2.sensor3", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle1.device1.sensor1", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle1.device1.sensor1", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle1.device1.sensor2", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle1.device1.sensor2", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle1.device1.sensor3", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle1.device1.sensor3", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle1.device2.sensor1", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle1.device2.sensor1", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle1.device2.sensor2", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle1.device2.sensor2", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
-    mManager.addPathToMTree("root.vehicle1.device2.sensor3", TSDataType.valueOf("INT32"),
+    mManager.createTimeseries("root.vehicle1.device2.sensor3", TSDataType.valueOf("INT32"),
         TSEncoding.valueOf("RLE"), compressionType, Collections
             .emptyMap());
   }
@@ -113,10 +113,6 @@ public class PlannerTest {
     PhysicalPlan plan4 = processor.parseSQLToPhysicalPlan(insertStatement);
     assertEquals(OperatorType.INSERT, plan4.getOperatorType());
 
-    String propertyStatement = "add label label1021 to property propropro";
-    PhysicalPlan plan5 = processor.parseSQLToPhysicalPlan(propertyStatement);
-    assertEquals(OperatorType.PROPERTY, plan5.getOperatorType());
-
     String deleteStatement = "DELETE FROM root.device0.sensor0,root.device0.sensor1 WHERE time <= 5000";
     PhysicalPlan plan6 = processor.parseSQLToPhysicalPlan(deleteStatement);
     assertEquals(OperatorType.DELETE, plan6.getOperatorType());
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/other/TSPlanContextPropertyTest.java b/server/src/test/java/org/apache/iotdb/db/qp/other/TSPlanContextPropertyTest.java
deleted file mode 100644
index cd9b37b..0000000
--- a/server/src/test/java/org/apache/iotdb/db/qp/other/TSPlanContextPropertyTest.java
+++ /dev/null
@@ -1,89 +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.qp.other;
-
-import static org.junit.Assert.assertArrayEquals;
-import static org.junit.Assert.assertEquals;
-
-import java.util.Arrays;
-import java.util.Collection;
-import org.apache.iotdb.db.exception.query.QueryProcessException;
-import org.apache.iotdb.db.qp.Planner;
-import org.apache.iotdb.db.qp.logical.sys.PropertyOperator.PropertyType;
-import org.apache.iotdb.db.qp.physical.sys.PropertyPlan;
-import org.apache.iotdb.tsfile.read.common.Path;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-/**
- * test ast node parsing on authorization
- */
-@RunWith(Parameterized.class)
-public class TSPlanContextPropertyTest {
-
-  private static Path defaultMetadataPath = new Path("root.m1.m2");
-  private static Path defaultPropertyPath = new Path("property1");
-  private static Path defaultPropertyLabelPath = new Path("property1.label1");
-
-  private String inputSQL;
-  private PropertyType propertyType;
-  private Path propertyPath;
-  private Path metadataPath;
-  private Path[] paths;
-
-  public TSPlanContextPropertyTest(String inputSQL, PropertyType propertyType, Path propertyPath,
-      Path metadataPath,
-      Path[] paths) {
-    this.inputSQL = inputSQL;
-    this.propertyType = propertyType;
-    this.propertyPath = propertyPath;
-    this.metadataPath = metadataPath;
-    this.paths = paths;
-  }
-
-  @Parameters
-  public static Collection<Object[]> data() {
-    return Arrays.asList(new Object[][]{
-        {"CREATE PROPERTY property1", PropertyType.ADD_TREE, defaultPropertyPath, null,
-            new Path[]{defaultPropertyPath}},
-        {"ADD LABEL label1 TO PROPERTY property1", PropertyType.ADD_PROPERTY_LABEL,
-            defaultPropertyLabelPath,
-            null, new Path[]{defaultPropertyLabelPath}},
-        {"DELETE LABEL label1 FROM PROPERTY property1", PropertyType.DELETE_PROPERTY_LABEL,
-            defaultPropertyLabelPath, null, new Path[]{defaultPropertyLabelPath}},
-        {"LINK root.m1.m2 TO property1.label1", PropertyType.ADD_PROPERTY_TO_METADATA,
-            defaultPropertyLabelPath, defaultMetadataPath,
-            new Path[]{defaultMetadataPath, defaultPropertyLabelPath}},
-        {"UNLINK root.m1.m2 FROM property1.label1", PropertyType.DEL_PROPERTY_FROM_METADATA,
-            defaultPropertyLabelPath, defaultMetadataPath,
-            new Path[]{defaultMetadataPath, defaultPropertyLabelPath}},});
-  }
-
-  @Test
-  public void testAnalyzeMetadata() throws QueryProcessException {
-    Planner processor = new Planner();
-    PropertyPlan plan = (PropertyPlan) processor.parseSQLToPhysicalPlan(inputSQL);
-    assertEquals(propertyType, plan.getPropertyType());
-    assertEquals(propertyPath, plan.getPropertyPath());
-    assertEquals(metadataPath, plan.getMetadataPath());
-    assertArrayEquals(paths, plan.getPaths().toArray());
-  }
-}
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/plan/TestConcatOptimizer.java b/server/src/test/java/org/apache/iotdb/db/qp/plan/ConcatOptimizerTest.java
similarity index 82%
rename from server/src/test/java/org/apache/iotdb/db/qp/plan/TestConcatOptimizer.java
rename to server/src/test/java/org/apache/iotdb/db/qp/plan/ConcatOptimizerTest.java
index 67eff44..f6d6b67 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/plan/TestConcatOptimizer.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/plan/ConcatOptimizerTest.java
@@ -23,7 +23,7 @@ import static org.junit.Assert.assertEquals;
 import java.io.IOException;
 import org.antlr.v4.runtime.RecognitionException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.qp.Planner;
@@ -44,7 +44,7 @@ import org.junit.Test;
 /**
  * test the correctness of {@linkplain ConcatPathOptimizer ConcatPathOptimizer}
  */
-public class TestConcatOptimizer {
+public class ConcatOptimizerTest {
 
   private Planner processor;
 
@@ -52,20 +52,19 @@ public class TestConcatOptimizer {
   public void before() throws MetadataException, PathException {
     processor = new Planner();
     MManager.getInstance().init();
-    MManager.getInstance().setStorageGroupToMTree("root.laptop");
-    MManager.getInstance().addPathToMTree("root.laptop.d1.s1", TSDataType.INT64, TSEncoding.PLAIN,
+    MManager.getInstance().setStorageGroup("root.laptop");
+    MManager.getInstance().createTimeseries("root.laptop.d1.s1", TSDataType.INT64, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, null);
-    MManager.getInstance().addPathToMTree("root.laptop.d1.s2", TSDataType.INT64, TSEncoding.PLAIN,
+    MManager.getInstance().createTimeseries("root.laptop.d1.s2", TSDataType.INT64, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, null);
-    MManager.getInstance().addPathToMTree("root.laptop.d2.s1", TSDataType.INT64, TSEncoding.PLAIN,
+    MManager.getInstance().createTimeseries("root.laptop.d2.s1", TSDataType.INT64, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, null);
-    MManager.getInstance().addPathToMTree("root.laptop.d2.s2", TSDataType.INT64, TSEncoding.PLAIN,
+    MManager.getInstance().createTimeseries("root.laptop.d2.s2", TSDataType.INT64, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, null);
-    MManager.getInstance().addPathToMTree("root.laptop.d3.s1", TSDataType.INT64, TSEncoding.PLAIN,
+    MManager.getInstance().createTimeseries("root.laptop.d3.s1", TSDataType.INT64, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, null);
-    MManager.getInstance().addPathToMTree("root.laptop.d3.s2", TSDataType.INT64, TSEncoding.PLAIN,
+    MManager.getInstance().createTimeseries("root.laptop.d3.s2", TSDataType.INT64, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, null);
-
   }
 
   @After
@@ -91,7 +90,7 @@ public class TestConcatOptimizer {
   }
 
   @Test
-  public void testConcat3() throws QueryProcessException, RecognitionException{
+  public void testConcat3() throws QueryProcessException, RecognitionException {
     String inputSQL = "select s1 from root.laptop.d1 where s1 < 10";
     PhysicalPlan plan = processor.parseSQLToPhysicalPlan(inputSQL);
     SingleSeriesExpression seriesExpression = new SingleSeriesExpression(
@@ -99,5 +98,4 @@ public class TestConcatOptimizer {
         ValueFilter.lt(10));
     assertEquals(seriesExpression.toString(), ((RawDataQueryPlan) plan).getExpression().toString());
   }
-
 }
\ No newline at end of file
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java b/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java
index 7ee1e91..c2371c9 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/plan/PhysicalPlanTest.java
@@ -43,7 +43,6 @@ import org.apache.iotdb.db.qp.physical.sys.CreateTimeSeriesPlan;
 import org.apache.iotdb.db.qp.physical.sys.DataAuthPlan;
 import org.apache.iotdb.db.qp.physical.sys.LoadConfigurationPlan;
 import org.apache.iotdb.db.qp.physical.sys.OperateFilePlan;
-import org.apache.iotdb.db.qp.physical.sys.PropertyPlan;
 import org.apache.iotdb.db.qp.physical.sys.ShowPlan;
 import org.apache.iotdb.db.query.fill.LinearFill;
 import org.apache.iotdb.db.query.fill.PreviousFill;
@@ -71,14 +70,14 @@ public class PhysicalPlanTest {
   @Before
   public void before() throws QueryProcessException, MetadataException {
     MManager.getInstance().init();
-    MManager.getInstance().setStorageGroupToMTree("root.vehicle");
-    MManager.getInstance().addPathToMTree("root.vehicle.d1.s1", TSDataType.FLOAT, TSEncoding.PLAIN,
+    MManager.getInstance().setStorageGroup("root.vehicle");
+    MManager.getInstance().createTimeseries("root.vehicle.d1.s1", TSDataType.FLOAT, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, null);
-    MManager.getInstance().addPathToMTree("root.vehicle.d2.s1", TSDataType.FLOAT, TSEncoding.PLAIN,
+    MManager.getInstance().createTimeseries("root.vehicle.d2.s1", TSDataType.FLOAT, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, null);
-    MManager.getInstance().addPathToMTree("root.vehicle.d3.s1", TSDataType.FLOAT, TSEncoding.PLAIN,
+    MManager.getInstance().createTimeseries("root.vehicle.d3.s1", TSDataType.FLOAT, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, null);
-    MManager.getInstance().addPathToMTree("root.vehicle.d4.s1", TSDataType.FLOAT, TSEncoding.PLAIN,
+    MManager.getInstance().createTimeseries("root.vehicle.d4.s1", TSDataType.FLOAT, TSEncoding.PLAIN,
         CompressionType.UNCOMPRESSED, null);
   }
 
@@ -118,19 +117,6 @@ public class PhysicalPlanTest {
   }
 
   @Test
-  public void testProperty() throws QueryProcessException {
-    String sql = "add label label1021 to property propropro";
-    Planner processor = new Planner();
-    PropertyPlan plan = (PropertyPlan) processor.parseSQLToPhysicalPlan(sql);
-    assertEquals(
-        "propertyPath: propropro.label1021\n" + "metadataPath: null\n"
-            + "propertyType: ADD_PROPERTY_LABEL",
-        plan.toString());
-  }
-
-  // TODO uncomment these code when implement aggregation and fill function
-
-  @Test
   public void testAggregation() throws QueryProcessException {
     String sqlStr = "select sum(d1.s1) " + "from root.vehicle "
         + "where time <= 51 or !(time != 100 and time < 460)";
@@ -214,8 +200,10 @@ public class PhysicalPlanTest {
     int defaultFillInterval = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
     FillQueryPlan mergePlan = (FillQueryPlan) plan;
     assertEquals(5000, mergePlan.getQueryTime());
-    assertEquals(defaultFillInterval, ((LinearFill) mergePlan.getFillType().get(TSDataType.INT32)).getBeforeRange());
-    assertEquals(defaultFillInterval, ((LinearFill) mergePlan.getFillType().get(TSDataType.INT32)).getAfterRange());
+    assertEquals(defaultFillInterval,
+        ((LinearFill) mergePlan.getFillType().get(TSDataType.INT32)).getBeforeRange());
+    assertEquals(defaultFillInterval,
+        ((LinearFill) mergePlan.getFillType().get(TSDataType.INT32)).getAfterRange());
     assertEquals(defaultFillInterval,
         ((PreviousFill) mergePlan.getFillType().get(TSDataType.BOOLEAN)).getBeforeRange());
   }
diff --git a/server/src/test/java/org/apache/iotdb/db/query/executor/GroupByEngineDataSetTest.java b/server/src/test/java/org/apache/iotdb/db/query/executor/GroupByEngineDataSetTest.java
index 68efed7..1b08468 100644
--- a/server/src/test/java/org/apache/iotdb/db/query/executor/GroupByEngineDataSetTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/query/executor/GroupByEngineDataSetTest.java
@@ -21,7 +21,7 @@ package org.apache.iotdb.db.query.executor;
 import java.io.IOException;
 import java.util.ArrayList;
 import org.apache.iotdb.db.exception.StorageEngineException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.qp.physical.crud.GroupByPlan;
 import org.apache.iotdb.db.query.aggregation.impl.CountAggrResult;
 import org.apache.iotdb.db.query.dataset.groupby.GroupByEngineDataSet;
diff --git a/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesAggregateReaderTest.java b/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesAggregateReaderTest.java
index 0c6016b..c7f3bc9 100644
--- a/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesAggregateReaderTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesAggregateReaderTest.java
@@ -30,7 +30,7 @@ import org.apache.iotdb.db.engine.querycontext.QueryDataSource;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.query.aggregation.AggregateResult;
 import org.apache.iotdb.db.query.context.QueryContext;
diff --git a/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderByTimestampTest.java b/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderByTimestampTest.java
index a3348e5..a0cdba0 100644
--- a/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderByTimestampTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderByTimestampTest.java
@@ -23,7 +23,7 @@ import org.apache.iotdb.db.engine.querycontext.QueryDataSource;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
diff --git a/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderTest.java b/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderTest.java
index 77a31c1..e447d94 100644
--- a/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderTest.java
@@ -29,7 +29,7 @@ import java.util.List;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.StorageEngineException;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
diff --git a/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderTestUtil.java b/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderTestUtil.java
index e4bb7f5..d2beb19 100644
--- a/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderTestUtil.java
+++ b/server/src/test/java/org/apache/iotdb/db/query/reader/series/SeriesReaderTestUtil.java
@@ -32,7 +32,7 @@ import org.apache.iotdb.db.engine.cache.TsFileMetaDataCache;
 import org.apache.iotdb.db.engine.merge.manage.MergeManager;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
+import org.apache.iotdb.db.exception.query.PathException;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.query.control.FileReaderManager;
 import org.apache.iotdb.db.utils.EnvironmentUtils;
@@ -151,10 +151,10 @@ public class SeriesReaderTestUtil {
     for (int i = 0; i < deviceNum; i++) {
       deviceIds.add(SERIES_READER_TEST_SG + PATH_SEPARATOR + "device" + i);
     }
-    MManager.getInstance().setStorageGroupToMTree(SERIES_READER_TEST_SG);
+    MManager.getInstance().setStorageGroup(SERIES_READER_TEST_SG);
     for (String device : deviceIds) {
       for (MeasurementSchema measurementSchema : measurementSchemas) {
-        MManager.getInstance().addPathToMTree(
+        MManager.getInstance().createTimeseries(
             device + PATH_SEPARATOR + measurementSchema.getMeasurementId(), measurementSchema
                 .getType(), measurementSchema.getEncodingType(), measurementSchema.getCompressor(),
             Collections.emptyMap());
diff --git a/server/src/test/java/org/apache/iotdb/db/sync/receiver/load/FileLoaderTest.java b/server/src/test/java/org/apache/iotdb/db/sync/receiver/load/FileLoaderTest.java
index c74a96b..b733311 100644
--- a/server/src/test/java/org/apache/iotdb/db/sync/receiver/load/FileLoaderTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/sync/receiver/load/FileLoaderTest.java
@@ -72,9 +72,9 @@ public class FileLoaderTest {
     MManager mmanager = MManager.getInstance();
     mmanager.init();
     mmanager.clear();
-    mmanager.setStorageGroupToMTree("root.sg0");
-    mmanager.setStorageGroupToMTree("root.sg1");
-    mmanager.setStorageGroupToMTree("root.sg2");
+    mmanager.setStorageGroup("root.sg0");
+    mmanager.setStorageGroup("root.sg1");
+    mmanager.setStorageGroup("root.sg2");
   }
 
   @After
diff --git a/server/src/test/java/org/apache/iotdb/db/sync/receiver/recover/SyncReceiverLogAnalyzerTest.java b/server/src/test/java/org/apache/iotdb/db/sync/receiver/recover/SyncReceiverLogAnalyzerTest.java
index 3fd15e2..065ee01 100644
--- a/server/src/test/java/org/apache/iotdb/db/sync/receiver/recover/SyncReceiverLogAnalyzerTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/sync/receiver/recover/SyncReceiverLogAnalyzerTest.java
@@ -77,9 +77,9 @@ public class SyncReceiverLogAnalyzerTest {
     MManager mmanager = MManager.getInstance();
     mmanager.init();
     mmanager.clear();
-    mmanager.setStorageGroupToMTree("root.sg0");
-    mmanager.setStorageGroupToMTree("root.sg1");
-    mmanager.setStorageGroupToMTree("root.sg2");
+    mmanager.setStorageGroup("root.sg0");
+    mmanager.setStorageGroup("root.sg1");
+    mmanager.setStorageGroup("root.sg2");
   }
 
   @After
diff --git a/server/src/test/java/org/apache/iotdb/db/sync/sender/manage/SyncFileManagerTest.java b/server/src/test/java/org/apache/iotdb/db/sync/sender/manage/SyncFileManagerTest.java
index b8d8eb0..e4c1e94 100644
--- a/server/src/test/java/org/apache/iotdb/db/sync/sender/manage/SyncFileManagerTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/sync/sender/manage/SyncFileManagerTest.java
@@ -77,7 +77,7 @@ public class SyncFileManagerTest {
 
     Random r = new Random(0);
     for (int i = 0; i < 3; i++) {
-      MManager.getInstance().setStorageGroupToMTree(getSgName(i));
+      MManager.getInstance().setStorageGroup(getSgName(i));
     }
     for (int i = 0; i < 3; i++) {
       for (int j = 0; j < 5; j++) {
diff --git a/server/src/test/java/org/apache/iotdb/db/sync/sender/recover/SyncSenderLogAnalyzerTest.java b/server/src/test/java/org/apache/iotdb/db/sync/sender/recover/SyncSenderLogAnalyzerTest.java
index 3135a31..15a83d0 100644
--- a/server/src/test/java/org/apache/iotdb/db/sync/sender/recover/SyncSenderLogAnalyzerTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/sync/sender/recover/SyncSenderLogAnalyzerTest.java
@@ -83,7 +83,7 @@ public class SyncSenderLogAnalyzerTest {
     Map<String, Map<Long, Set<File>>> allFileList = new HashMap<>();
 
     for (int i = 0; i < 3; i++) {
-      MManager.getInstance().setStorageGroupToMTree(getSgName(i));
+      MManager.getInstance().setStorageGroup(getSgName(i));
     }
     Random r = new Random(0);
     for (int i = 0; i < 3; i++) {
diff --git a/server/src/test/java/org/apache/iotdb/db/writelog/PerformanceTest.java b/server/src/test/java/org/apache/iotdb/db/writelog/PerformanceTest.java
index 2a8150f..109a454 100644
--- a/server/src/test/java/org/apache/iotdb/db/writelog/PerformanceTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/writelog/PerformanceTest.java
@@ -23,7 +23,6 @@ import java.io.IOException;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.exception.metadata.MetadataException;
-import org.apache.iotdb.db.exception.path.PathException;
 import org.apache.iotdb.db.exception.storageGroup.StorageGroupException;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.qp.physical.crud.DeletePlan;
@@ -115,7 +114,7 @@ public class PerformanceTest {
 
   @Test
   public void recoverTest()
-      throws IOException, PathException, StorageGroupException {
+      throws IOException, MetadataException, StorageGroupException {
     // this test insert 1000000 * 3 logs , recover from them and report elapsed time
     if (skip) {
       return;
@@ -127,25 +126,25 @@ public class PerformanceTest {
     tempProcessorStore.createNewFile();
 
     try {
-      MManager.getInstance().setStorageGroupToMTree("root.logTestDevice");
+      MManager.getInstance().setStorageGroup("root.logTestDevice");
     } catch (MetadataException ignored) {
     }
-    MManager.getInstance().addPathToMTree("root.logTestDevice.s1",
+    MManager.getInstance().createTimeseries("root.logTestDevice.s1",
         TSDataType.DOUBLE.name(),
         TSEncoding.PLAIN.name());
     MManager.getInstance()
-        .addPathToMTree("root.logTestDevice.s2", TSDataType.INT32.name(),
+        .createTimeseries("root.logTestDevice.s2", TSDataType.INT32.name(),
             TSEncoding.PLAIN.name());
     MManager.getInstance()
-        .addPathToMTree("root.logTestDevice.s3", TSDataType.TEXT.name(),
+        .createTimeseries("root.logTestDevice.s3", TSDataType.TEXT.name(),
             TSEncoding.PLAIN.name());
-    MManager.getInstance().addPathToMTree("root.logTestDevice.s4", TSDataType.BOOLEAN.name(),
+    MManager.getInstance().createTimeseries("root.logTestDevice.s4", TSDataType.BOOLEAN.name(),
         TSEncoding.PLAIN.name());
     WriteLogNode logNode = new ExclusiveWriteLogNode("root.logTestDevice");
 
     for (int i = 0; i < 1000000; i++) {
       InsertPlan bwInsertPlan = new InsertPlan("root.logTestDevice", 100,
-      new String[]{"s1", "s2", "s3", "s4"}, new String[]{"1.0", "15", "str", "false"});
+          new String[]{"s1", "s2", "s3", "s4"}, new String[]{"1.0", "15", "str", "false"});
       UpdatePlan updatePlan = new UpdatePlan(0, 100, "2.0",
           new Path("root.logTestDevice.s1"));
       DeletePlan deletePlan = new DeletePlan(50, new Path("root.logTestDevice.s1"));
diff --git a/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java b/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
index ebcfc9c..b5aa64f 100644
--- a/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
+++ b/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
@@ -23,8 +23,9 @@ public enum TSStatusCode {
   SUCCESS_STATUS(200),
   STILL_EXECUTING_STATUS(201),
   INVALID_HANDLE_STATUS(202),
-  TIMESERIES_ALREADY_EXIST_ERROR(300),
-  TIMESERIES_NOT_EXIST_ERROR(301),
+
+  PATH_ALREADY_EXIST_ERROR(300),
+  PATH_NOT_EXIST_ERROR(301),
   UNSUPPORTED_FETCH_METADATA_OPERATION_ERROR(302),
   METADATA_ERROR(303),
   OUT_OF_TTL_ERROR(305),
@@ -37,6 +38,8 @@ public enum TSStatusCode {
   STORAGE_GROUP_ERROR(312),
   STORAGE_ENGINE_ERROR(313),
   TSFILE_PROCESSOR_ERROR(314),
+  PATH_ILLEGAL(315),
+
   EXECUTE_STATEMENT_ERROR(400),
   SQL_PARSE_ERROR(401),
   GENERATE_TIME_ZONE_ERROR(402),
@@ -49,6 +52,7 @@ public enum TSStatusCode {
   UNSUPPORTED_FILL_TYPE_ERROR(409),
   PATH_ERROR(410),
   QUERY_PROCESS_ERROR(411),
+
   INTERNAL_SERVER_ERROR(500),
   CLOSE_OPERATION_ERROR(501),
   READ_ONLY_SYSTEM_ERROR(502),
diff --git a/session/src/test/java/org/apache/iotdb/session/IoTDBSessionIT.java b/session/src/test/java/org/apache/iotdb/session/IoTDBSessionIT.java
index 31731b7..502e20b 100644
--- a/session/src/test/java/org/apache/iotdb/session/IoTDBSessionIT.java
+++ b/session/src/test/java/org/apache/iotdb/session/IoTDBSessionIT.java
@@ -495,7 +495,7 @@ public class IoTDBSessionIT {
         CompressionType.SNAPPY);
     // using the query result as the QueryTest to verify the deletion and the new insertion
     Class.forName(Config.JDBC_DRIVER_NAME);
-    String standard = "Time\n" + "root.sg1.d1.s1\n" + "root.sg2.d1.s1\n";
+    String standard = "Time\n" + "root.sg2.d1.s1\n" + "root.sg1.d1.s1\n";
     try (Connection connection = DriverManager
         .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
         Statement statement = connection.createStatement()) {
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/common/conf/TSFileConfig.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/common/conf/TSFileConfig.java
index 670e2c8..8a690ad 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/common/conf/TSFileConfig.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/common/conf/TSFileConfig.java
@@ -19,6 +19,7 @@
 package org.apache.iotdb.tsfile.common.conf;
 
 import java.nio.charset.Charset;
+import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.fileSystem.FSType;
 
 /**
@@ -130,7 +131,7 @@ public class TSFileConfig {
    * Data compression method, TsFile supports UNCOMPRESSED or SNAPPY. Default value is UNCOMPRESSED
    * which means no compression
    */
-  private String compressor = "UNCOMPRESSED";
+  private CompressionType compressor = CompressionType.SNAPPY;
   /**
    * Line count threshold for checking page memory occupied size.
    */
@@ -320,12 +321,12 @@ public class TSFileConfig {
     this.dftSatisfyRate = dftSatisfyRate;
   }
 
-  public String getCompressor() {
+  public CompressionType getCompressor() {
... 108 lines suppressed ...