You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ji...@apache.org on 2019/11/05 12:14:21 UTC

[incubator-iotdb] branch refactor_metadata created (now f6be8aa)

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

jiangtian pushed a change to branch refactor_metadata
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git.


      at f6be8aa  refactor MGraph

This branch includes the following new commits:

     new f6be8aa  refactor MGraph

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[incubator-iotdb] 01/01: refactor MGraph

Posted by ji...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f6be8aab3b15fe2da46766797cadf357821bfdb7
Author: jt2594838 <jt...@163.com>
AuthorDate: Tue Nov 5 20:13:54 2019 +0800

    refactor MGraph
---
 .../apache/iotdb/jdbc/IoTDBDatabaseMetadata.java   |   4 +-
 .../apache/iotdb/jdbc/IoTDBMetadataResultSet.java  |   4 +-
 .../iotdb/jdbc/IoTDBDatabaseMetadataTest.java      |  12 +-
 .../org/apache/iotdb/jdbc/IoTDBStatementTest.java  |   8 +-
 .../org/apache/iotdb/db/engine/StorageEngine.java  |   3 +-
 .../java/org/apache/iotdb/db/metadata/MGraph.java  | 207 +++-------
 .../org/apache/iotdb/db/metadata/MManager.java     | 212 +---------
 .../java/org/apache/iotdb/db/metadata/MTree.java   | 425 +++++++--------------
 .../org/apache/iotdb/db/metadata/MetaUtils.java    |  74 +++-
 .../org/apache/iotdb/db/metadata/Metadata.java     | 125 ------
 .../apache/iotdb/db/metadata/MetadataConstant.java |  27 --
 .../iotdb/db/metadata/MetadataOperationType.java   |  20 +-
 .../java/org/apache/iotdb/db/metadata/PTree.java   |  33 +-
 .../org/apache/iotdb/db/service/TSServiceImpl.java |  19 +-
 .../db/sync/receiver/transfer/SyncServiceImpl.java |   3 +-
 .../sync/sender/transfer/DataTransferManager.java  |   6 +-
 .../org/apache/iotdb/db/utils/SchemaUtils.java     |  54 ++-
 .../iotdb/db/engine/storagegroup/TTLTest.java      |  15 +-
 .../iotdb/db/integration/IoTDBQuotedPathIT.java    | 106 ++---
 .../apache/iotdb/db/integration/IoTDBTtlIT.java    |  20 +-
 .../org/apache/iotdb/db/metadata/MGraphTest.java   |  37 +-
 .../iotdb/db/metadata/MManagerAdvancedTest.java    |  18 +-
 .../iotdb/db/metadata/MManagerImproveTest.java     |  40 +-
 .../org/apache/iotdb/db/metadata/MTreeTest.java    |  78 ++--
 .../org/apache/iotdb/db/metadata/MetadataTest.java |  88 -----
 service-rpc/rpc-changelist.md                      |   3 +-
 service-rpc/src/main/thrift/rpc.thrift             |   7 +-
 .../tsfile/common/constant/TsFileConstant.java     |   2 +-
 .../org/apache/iotdb/tsfile/read/common/Path.java  |   2 +-
 29 files changed, 532 insertions(+), 1120 deletions(-)

diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java
index c88aac9..561604b 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadata.java
@@ -113,7 +113,7 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
           } catch (IoTDBRPCException e) {
             throw new IoTDBSQLException(e.getMessage(), resp.getStatus());
           }
-          Set<String> showStorageGroup = resp.getStorageGroups();
+          List<String> showStorageGroup = resp.getStorageGroups();
           return new IoTDBMetadataResultSet(showStorageGroup, MetadataType.STORAGE_GROUP);
         } catch (TException e) {
           throw new TException("Connection error when fetching storage group metadata", e);
@@ -128,7 +128,7 @@ public class IoTDBDatabaseMetadata implements DatabaseMetaData {
           } catch (IoTDBRPCException e) {
             throw new IoTDBSQLException(e.getMessage(), resp.getStatus());
           }
-          List<List<String>> showTimeseriesList = resp.getTimeseriesList();
+          List<List<String>> showTimeseriesList = resp.getTimeseriesInfoList();
           return new IoTDBMetadataResultSet(showTimeseriesList, MetadataType.TIMESERIES);
         } catch (TException e) {
           throw new TException("Connection error when fetching timeseries metadata", e);
diff --git a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBMetadataResultSet.java b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBMetadataResultSet.java
index c1e319a..4c70cd0 100644
--- a/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBMetadataResultSet.java
+++ b/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBMetadataResultSet.java
@@ -69,13 +69,13 @@ public class IoTDBMetadataResultSet extends IoTDBQueryResultSet {
         columnItr = columns.iterator();
         break;
       case STORAGE_GROUP:
-        Set<String> storageGroupSet = (Set<String>) object;
+        List<String> storageGroupSet = (List<String>) object;
         colCount = 1;
         showLabels = new String[]{"Storage Group"};
         columnItr = storageGroupSet.iterator();
         break;
       case DEVICES:
-        Set<String> devicesSet = (Set<String>) object;
+        List<String> devicesSet = (List<String>) object;
         colCount = 1;
         showLabels = new String[]{"Device"};
         columnItr = devicesSet.iterator();
diff --git a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
index 43f79e2..5903294 100644
--- a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
+++ b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
@@ -271,7 +271,7 @@ public class IoTDBDatabaseMetadataTest {
   @SuppressWarnings("resource")
   @Test
   public void device() {
-    Set<String> devicesSet = new HashSet<>();
+    List<String> devicesSet = new ArrayList<>();
     devicesSet.add("root.vehicle.d0");
 
     when(fetchMetadataResp.getDevices()).thenReturn(devicesSet);
@@ -332,7 +332,7 @@ public class IoTDBDatabaseMetadataTest {
       }
     });
 
-    when(fetchMetadataResp.getTimeseriesList()).thenReturn(tsList);
+    when(fetchMetadataResp.getTimeseriesInfoList()).thenReturn(tsList);
 
     String standard = "Timeseries,Storage Group,DataType,Encoding,\n"
         + "root.vehicle.d0.s0,root.vehicle,INT32,RLE,\n"
@@ -376,7 +376,7 @@ public class IoTDBDatabaseMetadataTest {
       }
     });
 
-    when(fetchMetadataResp.getTimeseriesList()).thenReturn(tsList);
+    when(fetchMetadataResp.getTimeseriesInfoList()).thenReturn(tsList);
 
     String standard = "DataType,\n" + "INT32,\n";
     try (ResultSet resultSet = databaseMetaData
@@ -403,9 +403,9 @@ public class IoTDBDatabaseMetadataTest {
   @SuppressWarnings("resource")
   @Test
   public void ShowStorageGroup() {
-    Set<String> sgSet = new HashSet<>();
-    sgSet.add("root.vehicle");
-    when(fetchMetadataResp.getStorageGroups()).thenReturn(sgSet);
+    List<String> sgList = new ArrayList<>();
+    sgList.add("root.vehicle");
+    when(fetchMetadataResp.getStorageGroups()).thenReturn(sgList);
 
     String standard = "Storage Group,\n" + "root.vehicle,\n";
     try (ResultSet resultSet = databaseMetaData
diff --git a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java
index 5953fde..6cba428 100644
--- a/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java
+++ b/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java
@@ -28,9 +28,7 @@ import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.time.ZoneId;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
 import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.service.rpc.thrift.TSFetchMetadataReq;
 import org.apache.iotdb.service.rpc.thrift.TSFetchMetadataResp;
@@ -109,7 +107,7 @@ public class IoTDBStatementTest {
             + "root.vehicle.d0.s0,root.vehicle,INT32,RLE,\n"
             + "root.vehicle.d0.s1,root.vehicle,INT64,RLE,\n"
             + "root.vehicle.d0.s2,root.vehicle,FLOAT,RLE,\n";
-    when(fetchMetadataResp.getTimeseriesList()).thenReturn(tsList);
+    when(fetchMetadataResp.getTimeseriesInfoList()).thenReturn(tsList);
     boolean res = stmt.execute("show timeseries");
     assertTrue(res);
     try (ResultSet resultSet = stmt.getResultSet()) {
@@ -166,7 +164,7 @@ public class IoTDBStatementTest {
         + "root.vehicle.d0.s0,root.vehicle,INT32,RLE,\n"
         + "root.vehicle.d0.s1,root.vehicle,INT64,RLE,\n"
         + "root.vehicle.d0.s2,root.vehicle,FLOAT,RLE,\n";
-    when(fetchMetadataResp.getTimeseriesList()).thenReturn(tsList);
+    when(fetchMetadataResp.getTimeseriesInfoList()).thenReturn(tsList);
     boolean res = stmt.execute("show timeseries root.vehicle.d0");
     assertTrue(res);
     try (ResultSet resultSet = stmt.getResultSet()) {
@@ -193,7 +191,7 @@ public class IoTDBStatementTest {
   @Test
   public void testExecuteSQL3() throws SQLException {
     IoTDBStatement stmt = new IoTDBStatement(connection, client, sessHandle, zoneID);
-    Set<String> sgSet = new HashSet<>();
+    List<String> sgSet = new ArrayList<>();
     sgSet.add("root.vehicle");
     when(fetchMetadataResp.getStorageGroups()).thenReturn(sgSet);
     String standard = "Storage Group,\nroot.vehicle,\n";
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 db41982..b2b5868 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
@@ -28,7 +28,6 @@ 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;
@@ -179,7 +178,7 @@ public class StorageEngine implements IService {
                 storageGroupName, Thread.currentThread().getId());
             processor = new StorageGroupProcessor(systemDir, storageGroupName);
             processor.setDataTTL(
-                MManager.getInstance().getNodeByPathWithCheck(storageGroupName).getDataTTL());
+                MManager.getInstance().getNodeInStorageGroup(storageGroupName).getDataTTL());
             processorMap.put(storageGroupName, processor);
           }
         }
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
index b0618be..d12c0ed 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MGraph.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MGraph.java
@@ -18,18 +18,14 @@
  */
 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.conf.IoTDBConstant;
 import org.apache.iotdb.db.exception.MetadataErrorException;
 import org.apache.iotdb.db.exception.PathErrorException;
 import org.apache.iotdb.db.exception.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;
@@ -38,10 +34,9 @@ import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
 /**
  * Metadata Graph consists of one {@code MTree} and several {@code PTree}.
  */
-public class MGraph implements Serializable {
+public class MGraph {
 
-  private static final long serialVersionUID = 8214849219614352834L;
-  private static final String DOUB_SEPARATOR = "\\.";
+  private static final String ESCAPED_SEPARATOR = "\\.";
   private static final String TIME_SERIES_INCORRECT = "Timeseries's root is not Correct. RootName: ";
   private MTree mtree;
   private HashMap<String, PTree> ptreeMap;
@@ -55,7 +50,7 @@ public class MGraph implements Serializable {
    * Add a {@code PTree} to current {@code MGraph}.
    */
   void addAPTree(String ptreeRootName) throws MetadataErrorException {
-    if (MetadataConstant.ROOT.equalsIgnoreCase(ptreeRootName)) {
+    if (IoTDBConstant.PATH_ROOT.equalsIgnoreCase(ptreeRootName)) {
       throw new MetadataErrorException("Property Tree's root name should not be 'root'");
     }
     PTree ptree = new PTree(ptreeRootName, mtree);
@@ -63,29 +58,14 @@ public class MGraph implements Serializable {
   }
 
   /**
-   * this is just for compatibility
-   */
-  public void addPathToMTree(String path, String dataType, String encoding)
-      throws PathErrorException {
-    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 PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, DOUB_SEPARATOR);
-    if (nodes.length == 0) {
-      throw new PathErrorException("Timeseries is null");
-    }
-    mtree.addTimeseriesPath(path, dataType, encoding, compressor, props);
+    String[] nodes = MetaUtils.getNodeNames(path);
+    mtree.addTimeseriesPath(nodes, dataType, encoding, compressor, props);
   }
 
   /**
@@ -99,14 +79,12 @@ public class MGraph implements Serializable {
    * Add a seriesPath to {@code PTree}.
    */
   void addPathToPTree(String path) throws PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, DOUB_SEPARATOR);
-    if (nodes.length == 0) {
-      throw new PathErrorException("Timeseries is null.");
-    }
+    String[] nodes = MetaUtils.getNodeNames(path);
+
     String rootName = nodes[0];
     if (ptreeMap.containsKey(rootName)) {
       PTree ptree = ptreeMap.get(rootName);
-      ptree.addPath(path);
+      ptree.addPath(nodes);
     } else {
       throw new PathErrorException(TIME_SERIES_INCORRECT + rootName);
     }
@@ -118,10 +96,8 @@ public class MGraph implements Serializable {
    * @param path a seriesPath belongs to MTree or PTree
    */
   String deletePath(String path) throws PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, DOUB_SEPARATOR);
-    if (nodes.length == 0) {
-      throw new PathErrorException("Timeseries is null");
-    }
+    String[] nodes = MetaUtils.getNodeNames(path);
+
     String rootName = nodes[0];
     if (mtree.getRoot().getName().equals(rootName)) {
       return mtree.deletePath(path);
@@ -137,24 +113,26 @@ public class MGraph implements Serializable {
   /**
    * Link a {@code MNode} to a {@code PNode} in current PTree.
    */
-  void linkMNodeToPTree(String path, String mpath) throws PathErrorException {
-    String ptreeName = MetaUtils.getNodeNames(path, DOUB_SEPARATOR)[0];
-    if (!ptreeMap.containsKey(ptreeName)) {
-      throw new PathErrorException("Error: PTree Path Not Correct. Path: " + path);
+  void linkMNodeToPTree(String pPath, String mPath) throws PathErrorException {
+    String[] pNodes = MetaUtils.getNodeNames(pPath);
+    String pRootName = pNodes[0];
+    if (!ptreeMap.containsKey(pRootName)) {
+      throw new PathErrorException("Error: PTree Path Not Correct. Path: " + pPath);
     } else {
-      ptreeMap.get(ptreeName).linkMNode(path, mpath);
+      ptreeMap.get(pRootName).linkMNode(pNodes, mPath);
     }
   }
 
   /**
    * Unlink a {@code MNode} from a {@code PNode} in current PTree.
    */
-  void unlinkMNodeFromPTree(String path, String mpath) throws PathErrorException {
-    String ptreeName = MetaUtils.getNodeNames(path, DOUB_SEPARATOR)[0];
-    if (!ptreeMap.containsKey(ptreeName)) {
-      throw new PathErrorException("Error: PTree Path Not Correct. Path: " + path);
+  void unlinkMNodeFromPTree(String pPath, String mPath) throws PathErrorException {
+    String[] pNodes = MetaUtils.getNodeNames(pPath);
+    String pRootName = pNodes[0];
+    if (!ptreeMap.containsKey(pRootName)) {
+      throw new PathErrorException("Error: PTree Path Not Correct. Path: " + pPath);
     } else {
-      ptreeMap.get(ptreeName).unlinkMNode(path, mpath);
+      ptreeMap.get(pRootName).unlinkMNode(pNodes, mPath);
     }
   }
 
@@ -175,8 +153,9 @@ public class MGraph implements Serializable {
   void deleteStorageGroup(String path) throws PathErrorException {
     mtree.deleteStorageGroup(path);
   }
+
   /**
-   * Check whether the input path is storage group for current Metadata Tree or not.
+   * Check whether the input path is a storage group in current Metadata Tree or not.
    *
    * @param path Format: root.node.(node)*
    * @apiNote :for cluster
@@ -191,13 +170,14 @@ public class MGraph implements Serializable {
    * 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.
+   * @return A HashMap whose Keys are the storage group names.
    */
   HashMap<String, List<String>> getAllPathGroupByStorageGroup(String path)
       throws PathErrorException {
-    String rootName = MetaUtils.getNodeNames(path, DOUB_SEPARATOR)[0];
+    String[] nodes = MetaUtils.getNodeNames(path);
+    String rootName = nodes[0];
     if (mtree.getRoot().getName().equals(rootName)) {
-      return mtree.getAllPath(path);
+      return mtree.getAllPath(nodes);
     } else if (ptreeMap.containsKey(rootName)) {
       PTree ptree = ptreeMap.get(rootName);
       return ptree.getAllLinkedPath(path);
@@ -211,11 +191,14 @@ public class MGraph implements Serializable {
 
   /**
    * function for getting all timeseries paths under the given seriesPath.
+   * @return each list in the returned list consists of 4 strings: full path, storage group, data
+   *   type and encoding of a timeseries
    */
-  List<List<String>> getShowTimeseriesPath(String path) throws PathErrorException {
-    String rootName = MetaUtils.getNodeNames(path, DOUB_SEPARATOR)[0];
+  List<List<String>> getTimeseriesInfo(String path) throws PathErrorException {
+    String[] nodes = MetaUtils.getNodeNames(path);
+    String rootName = nodes[0];
     if (mtree.getRoot().getName().equals(rootName)) {
-      return mtree.getShowTimeseriesPath(path);
+      return mtree.getTimeseriesInfo(nodes);
     } else if (ptreeMap.containsKey(rootName)) {
       throw new PathErrorException(
           "PTree is not involved in the execution of the sql 'show timeseries " + path + "'");
@@ -223,56 +206,16 @@ public class MGraph implements Serializable {
     throw new PathErrorException(TIME_SERIES_INCORRECT + 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 PathErrorException {
-    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 PathErrorException {
-    return mtree.getDeviceForOneType(type);
-  }
-
-  /**
-   * Get all delta objects group by deviceId type.
-   */
-  private Map<String, List<String>> getDeviceForAllType() throws PathErrorException {
-    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 PathErrorException {
-    Map<String, List<String>> deviceIdMap = getDeviceForAllType();
-    return new Metadata(deviceIdMap);
-  }
-
   List<String> getAllStorageGroupNames() {
     return mtree.getAllStorageGroupList();
   }
 
-  Set<String> getAllDevices() throws SQLException {
+  List<String> getAllDevices() {
     return mtree.getAllDevices();
   }
 
-  List<String> getNodesList(String schemaPattern, int nodeLevel) throws SQLException {
-    return mtree.getNodesList(schemaPattern, nodeLevel);
+  List<String> getNodesList(String prefixPath, int nodeLevel) throws SQLException {
+    return mtree.getNodesList(prefixPath, nodeLevel);
   }
 
   List<String> getLeafNodePathInNextLevel(String path) throws PathErrorException {
@@ -280,43 +223,24 @@ public class MGraph implements Serializable {
   }
 
   /**
-   * 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 PathErrorException {
-    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
+   * @return List<'   ColumnSchema   '> The list of the schema
    */
-  ArrayList<MeasurementSchema> getSchemaInOneStorageGroup(String path) {
+  List<MeasurementSchema> getSchemaInOneStorageGroup(String path) {
     return mtree.getSchemaForOneStorageGroup(path);
   }
 
-  Map<String, MeasurementSchema> getSchemaMapForOneFileNode(String path) {
+  Map<String, MeasurementSchema> getSchemaMapInStorageGroup(String path) {
     return mtree.getSchemaMapForOneStorageGroup(path);
   }
 
-  Map<String, Integer> getNumSchemaMapForOneFileNode(String path) {
+  Map<String, Integer> getNumSchemaMapInStorageGroup(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 PathErrorException {
-    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.
    */
@@ -346,16 +270,14 @@ public class MGraph implements Serializable {
     return mtree.isPathExist(path);
   }
 
-  boolean pathExist(MNode node, String path) {
-    return mtree.isPathExist(node, path);
-  }
-
-  MNode getNodeByPath(String path) throws PathErrorException {
-    return mtree.getNode(path);
-  }
-
-  MNode getNodeByPathWithCheck(String path) throws PathErrorException, StorageGroupException {
-      return mtree.getNodeByPathWithStorageGroupCheck(path);
+  /**
+   *
+   * @param path
+   * @return an MNode corresponding to path
+   * @throws PathErrorException if the path does not exist or does not belong to a storage group.
+   */
+  MNode getNodeInStorageGroup(String path) throws PathErrorException {
+      return mtree.getNodeInStorageGroup(path);
   }
 
   /**
@@ -366,19 +288,6 @@ public class MGraph implements Serializable {
     return mtree.getSchemaForOnePath(path);
   }
 
-  MeasurementSchema getSchemaForOnePath(MNode node, String path) throws PathErrorException {
-    return mtree.getSchemaForOnePath(node, path);
-  }
-
-  MeasurementSchema getSchemaForOnePathWithCheck(MNode node, String path)
-      throws PathErrorException {
-    return mtree.getSchemaForOnePathWithCheck(node, path);
-  }
-
-  MeasurementSchema getSchemaForOnePathWithCheck(String path) throws PathErrorException {
-    return mtree.getSchemaForOnePathWithCheck(path);
-  }
-
   /**
    * functions for converting the mTree to a readable string in json format.
    */
@@ -388,21 +297,13 @@ public class MGraph implements Serializable {
   }
 
   /**
-   * 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 PathErrorException {
+  Map<String, Integer> countSeriesNumberInEachStorageGroup() {
     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());
+    List<MNode> storageGroups = getAllStorageGroupNodes();
+    for (MNode sg : storageGroups) {
+      res.put(sg.getFullPath(), sg.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 3102d7c..5678b9f 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
@@ -62,9 +62,10 @@ import org.slf4j.LoggerFactory;
  */
 public class MManager {
 
+  public static final String METADATA_LOG = "mlog.txt";
   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 ROOT_NAME = IoTDBConstant.PATH_ROOT;
   private static final String TIME_SERIES_TREE_HEADER = "===  Timeseries Tree  ===\n\n";
 
   // the lock for read/insert
@@ -96,7 +97,7 @@ public class MManager {
         logger.info("create system folder {} failed.", systemFolder.getAbsolutePath());
       }
     }
-    logFilePath = schemaDir + File.separator + MetadataConstant.METADATA_LOG;
+    logFilePath = schemaDir + File.separator + METADATA_LOG;
     writeToLog = false;
 
     int cacheSize = IoTDBDescriptor.getInstance().getConfig().getmManagerCacheSize();
@@ -121,8 +122,8 @@ public class MManager {
       @Override
       public MNode loadObjectByKey(String key) throws CacheException {
         try {
-          return getNodeByPathWithCheck(key);
-        } catch (PathErrorException | StorageGroupException e) {
+          return getNodeInStorageGroup(key);
+        } catch (PathErrorException e) {
           throw new CacheException(e);
         }
       }
@@ -373,7 +374,7 @@ public class MManager {
   }
 
   /**
-   * path will be added to mgraph with no check
+   * path will be added to MGraph with no check
    */
   private void addPathToMTreeInternal(String path, TSDataType dataType, TSEncoding encoding,
       CompressionType compressor, Map<String, String> props)
@@ -778,82 +779,11 @@ public class MManager {
   }
 
   /**
-   * function for getting series type.
-   */
-  public TSDataType getSeriesType(MNode node, String fullPath) throws PathErrorException {
-
-    lock.readLock().lock();
-    try {
-      return getSchemaForOnePath(node, fullPath).getType();
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting series type with check.
-   */
-  TSDataType getSeriesTypeWithCheck(MNode node, String fullPath) throws PathErrorException {
-
-    lock.readLock().lock();
-    try {
-      return getSchemaForOnePathWithCheck(node, fullPath).getType();
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * unction for getting series type with check.
-   */
-  TSDataType getSeriesTypeWithCheck(String fullPath) throws PathErrorException {
-
-    lock.readLock().lock();
-    try {
-      return getSchemaForOnePathWithCheck(fullPath).getType();
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * Get all device type in current Metadata Tree.
-   *
-   * @return a HashMap contains all distinct device type separated by device Type
-   */
-  // future feature
-  @SuppressWarnings("unused")
-  public Map<String, List<MeasurementSchema>> getSchemaForAllType() throws PathErrorException {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getSchemaForAllType();
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * Get the full Metadata info.
-   *
-   * @return A {@code Metadata} instance which stores all metadata info
-   */
-  public Metadata getMetadata() throws PathErrorException {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getMetadata();
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
    * Get the full devices info.
    *
    * @return A HashSet instance which stores all devices info
    */
-  public Set<String> getAllDevices() throws SQLException {
+  public List<String> getAllDevices() {
 
     lock.readLock().lock();
     try {
@@ -879,21 +809,6 @@ public class MManager {
   }
 
   /**
-   * @param path A seriesPath represented one Delta object
-   * @return a list contains all column schema
-   * @deprecated Get all MeasurementSchemas for given delta object type.
-   */
-  @Deprecated
-  public List<MeasurementSchema> getSchemaForOneType(String path) throws PathErrorException {
-    lock.readLock().lock();
-    try {
-      return mgraph.getSchemaForOneType(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
    * Get all MeasurementSchemas for the storage group seriesPath.
    */
   public List<MeasurementSchema> getSchemaForStorageGroup(String path) {
@@ -912,7 +827,7 @@ public class MManager {
 
     lock.readLock().lock();
     try {
-      return mgraph.getSchemaMapForOneFileNode(path);
+      return mgraph.getSchemaMapInStorageGroup(path);
     } finally {
       lock.readLock().unlock();
     }
@@ -925,24 +840,7 @@ public class MManager {
 
     lock.readLock().lock();
     try {
-      return mgraph.getNumSchemaMapForOneFileNode(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * Calculate the count of storage-group nodes included in given seriesPath.
-   *
-   * @return The total count of storage-group nodes.
-   */
-  // future feature
-  @SuppressWarnings("unused")
-  public int getFileCountForOneType(String path) throws PathErrorException {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getFileCountForOneType(path);
+      return mgraph.getNumSchemaMapInStorageGroup(path);
     } finally {
       lock.readLock().unlock();
     }
@@ -1075,22 +973,10 @@ public class MManager {
   /**
    * function for getting all timeseries paths under the given seriesPath.
    */
-  public List<List<String>> getShowTimeseriesPath(String path) throws PathErrorException {
+  public List<List<String>> getTimeseriesInfo(String path) throws PathErrorException {
     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 PathErrorException {
-    lock.readLock().lock();
-    try {
-      return mgraph.getLeafNodePathInNextLevel(path);
+      return mgraph.getTimeseriesInfo(path);
     } finally {
       lock.readLock().unlock();
     }
@@ -1110,31 +996,6 @@ public class MManager {
   }
 
   /**
-   * 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 PathErrorException {
-    lock.readLock().lock();
-    try {
-      return mgraph.getNodeByPath(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
    * function for getting node by deviceId from cache.
    */
   public MNode getNodeByDeviceIdFromCache(String deviceId) throws CacheException, PathErrorException {
@@ -1171,12 +1032,13 @@ public class MManager {
   }
 
   /**
-   * function for getting node by path with check.
+   * function for getting a node in a storage group by path. If the path does not belong to a
+   * storage group, PathErrorException will rise.
    */
-  public MNode getNodeByPathWithCheck(String path) throws PathErrorException, StorageGroupException {
+  public MNode getNodeInStorageGroup(String path) throws PathErrorException {
     lock.readLock().lock();
     try {
-      return mgraph.getNodeByPathWithCheck(path);
+      return mgraph.getNodeInStorageGroup(path);
     } finally {
       lock.readLock().unlock();
     }
@@ -1197,46 +1059,6 @@ public class MManager {
   }
 
   /**
-   * function for getting schema for one path.
-   */
-  private MeasurementSchema getSchemaForOnePath(MNode node, String path) throws PathErrorException {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getSchemaForOnePath(node, path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting schema for one path with check.
-   */
-  private MeasurementSchema getSchemaForOnePathWithCheck(MNode node, String path)
-      throws PathErrorException {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getSchemaForOnePathWithCheck(node, path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
-   * function for getting schema for one path with check.
-   */
-  private MeasurementSchema getSchemaForOnePathWithCheck(String path) throws PathErrorException {
-
-    lock.readLock().lock();
-    try {
-      return mgraph.getSchemaForOnePathWithCheck(path);
-    } finally {
-      lock.readLock().unlock();
-    }
-  }
-
-  /**
    * Check whether given seriesPath contains a MNode whose {@code MNode.isStorageGroup} is true.
    */
   public boolean checkFileLevel(List<Path> path) throws StorageGroupException {
@@ -1316,7 +1138,7 @@ public class MManager {
    */
   String getStorageGroupNameByAutoLevel(String fullPath, int level)
       throws PathErrorException {
-    String[] nodeNames = MetaUtils.getNodeNames(fullPath, DOUB_SEPARATOR);
+    String[] nodeNames = MetaUtils.getNodeNames(fullPath);
     StringBuilder storageGroupName = new StringBuilder(nodeNames[0]);
     if (nodeNames.length < level || !storageGroupName.toString().equals(ROOT_NAME)) {
       throw new PathErrorException(String.format("Timeseries %s is not right.", fullPath));
@@ -1399,7 +1221,7 @@ public class MManager {
   public void setTTL(String storageGroup, long dataTTL) throws PathErrorException, IOException {
     lock.writeLock().lock();
     try {
-      MNode sgNode = getNodeByPath(storageGroup);
+      MNode sgNode = getNodeInStorageGroup(storageGroup);
       if (!sgNode.isStorageGroup()) {
         throw new NotStorageGroupException(storageGroup);
       }
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 92e6f2e..431375b 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,25 +18,22 @@
  */
 package org.apache.iotdb.db.metadata;
 
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
-import com.alibaba.fastjson.serializer.SerializerFeature;
+import static org.apache.iotdb.tsfile.common.constant.TsFileConstant.PATH_SEPARATOR;
+import static org.apache.iotdb.tsfile.common.constant.TsFileConstant.PATH_SEPARATOR_NO_REGEX;
 
-import java.io.Serializable;
+import com.alibaba.fastjson.JSONObject;
 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.PathErrorException;
 import org.apache.iotdb.db.exception.StorageGroupException;
-import org.apache.iotdb.db.qp.constant.SQLConstant;
-import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
+import org.apache.iotdb.db.utils.SchemaUtils;
 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;
@@ -45,10 +42,8 @@ import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
 /**
  * The hierarchical struct of the Metadata Tree is implemented in this class.
  */
-public class MTree implements Serializable {
+public class MTree {
 
-  private static final long serialVersionUID = -4200394435237291964L;
-  private static final String PATH_SEPARATOR = "\\.";
   private static final String NO_CHILD_ERROR = "Timeseries is not correct. Node[%s] "
           + "doesn't have child named:%s";
   private static final String NOT_LEAF_NODE = "Timeseries %s is not the leaf node";
@@ -63,12 +58,13 @@ public class MTree implements Serializable {
   /**
    * function for adding timeseries.It should check whether seriesPath exists.
    */
-  void addTimeseriesPath(String timeseriesPath, TSDataType dataType, TSEncoding encoding,
+  void addTimeseriesPath(String[] nodeNames, TSDataType dataType, TSEncoding encoding,
       CompressionType compressor, Map<String, String> props) throws PathErrorException {
-      String[] nodeNames = MetaUtils.getNodeNames(timeseriesPath, PATH_SEPARATOR);
     if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) {
-      throw new PathErrorException(String.format("Timeseries %s is not right.", timeseriesPath));
+      throw new PathErrorException(String.format("Timeseries %s is not right.",
+          String.join(PATH_SEPARATOR, nodeNames)));
     }
+
     MNode cur = findLeafParent(nodeNames);
     String levelPath = cur.getDataFileName();
 
@@ -79,8 +75,8 @@ public class MTree implements Serializable {
     leaf.setDataFileName(levelPath);
     if (cur.isLeaf()) {
       throw new PathErrorException(
-              String.format("The Node [%s] is left node, the timeseries %s can't be created",
-                      cur.getName(), timeseriesPath));
+          String.format("The Node [%s] is left node, the timeseries %s can't be created",
+              cur.getName(), String.join(PATH_SEPARATOR, nodeNames)));
     }
     cur.addChild(nodeNames[nodeNames.length - 1], leaf);
   }
@@ -89,7 +85,7 @@ public class MTree implements Serializable {
    * function for adding deviceId
    */
   MNode addDeviceId(String deviceId) throws PathErrorException {
-    String[] nodeNames = MetaUtils.getNodeNames(deviceId, PATH_SEPARATOR);
+    String[] nodeNames = MetaUtils.getNodeNames(deviceId);
     if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) {
       throw new PathErrorException(String.format("Timeseries %s is not right.", deviceId));
     }
@@ -138,7 +134,12 @@ public class MTree implements Serializable {
    * @param path -seriesPath not necessarily the whole seriesPath (possibly a prefix of a sequence)
    */
   boolean isPathExist(String path) {
-    String[] nodeNames = nodeNames = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodeNames;
+    try {
+      nodeNames = MetaUtils.getNodeNames(path);
+    } catch (PathErrorException e) {
+      return false;
+    }
     MNode cur = root;
     int i = 0;
     while (i < nodeNames.length - 1) {
@@ -162,7 +163,12 @@ public class MTree implements Serializable {
    * function for checking whether the given path exists under the given mNode.
    */
   boolean isPathExist(MNode node, String path) {
-    String[] nodeNames = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodeNames;
+    try {
+      nodeNames = MetaUtils.getNodeNames(path);
+    } catch (PathErrorException e) {
+      return false;
+    }
     if (nodeNames.length < 1) {
       return true;
     }
@@ -193,7 +199,7 @@ public class MTree implements Serializable {
    * make sure check seriesPath before setting storage group.
    */
   public void setStorageGroup(String path) throws StorageGroupException {
-    String[] nodeNames = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodeNames = path.split(PATH_SEPARATOR_NO_REGEX);
     MNode cur = root;
     if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) {
       throw new StorageGroupException(
@@ -236,7 +242,7 @@ public class MTree implements Serializable {
     }
     cur.getParent().deleteChild(cur.getName());
     cur = cur.getParent();
-    while (cur != null && !MetadataConstant.ROOT.equals(cur.getName()) && cur.getChildren().size() == 0) {
+    while (cur != null && !IoTDBConstant.PATH_ROOT.equals(cur.getName()) && cur.getChildren().size() == 0) {
       cur.getParent().deleteChild(cur.getName());
       cur = cur.getParent();
     }
@@ -250,7 +256,7 @@ public class MTree implements Serializable {
    * @apiNote :for cluster
    */
   boolean checkStorageGroup(String path) {
-    String[] nodeNames = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodeNames = path.split(PATH_SEPARATOR_NO_REGEX);
     MNode cur = root;
     if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) {
       return false;
@@ -285,7 +291,7 @@ public class MTree implements Serializable {
    *             node.
    */
   String deletePath(String path) throws PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodes = MetaUtils.getNodeNames(path);
     if (nodes.length == 0 || !nodes[0].equals(getRoot().getName())) {
       throw new PathErrorException("Timeseries %s is not correct." + path);
     }
@@ -307,7 +313,7 @@ public class MTree implements Serializable {
     }
     cur.getParent().deleteChild(cur.getName());
     cur = cur.getParent();
-    while (cur != null && !MetadataConstant.ROOT.equals(cur.getName()) && cur.getChildren().size() == 0) {
+    while (cur != null && !IoTDBConstant.PATH_ROOT.equals(cur.getName()) && cur.getChildren().size() == 0) {
       if (cur.isStorageGroup()) {
         dataFileName = cur.getDataFileName();
         return dataFileName;
@@ -328,93 +334,21 @@ public class MTree implements Serializable {
     return leaf.getSchema();
   }
 
-  MeasurementSchema getSchemaForOnePath(MNode node, String path) throws PathErrorException {
-    MNode leaf = getLeafByPath(node, path);
-    return leaf.getSchema();
-  }
-
-  MeasurementSchema getSchemaForOnePathWithCheck(MNode node, String path)
-          throws PathErrorException {
-    MNode leaf = getLeafByPathWithCheck(node, path);
-    return leaf.getSchema();
-  }
-
-  MeasurementSchema getSchemaForOnePathWithCheck(String path) throws PathErrorException {
-    MNode leaf = getLeafByPathWithCheck(path);
-    return leaf.getSchema();
-  }
-
   private MNode getLeafByPath(String path) throws PathErrorException {
-    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()) {
+    MNode lastNode = getNode(path);
+    if (!lastNode.isLeaf()) {
       throw new PathErrorException(String.format(NOT_LEAF_NODE, path));
     }
-    return cur;
-  }
-
-  private MNode getLeafByPath(MNode node, String path) throws PathErrorException {
-    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 PathErrorException(String.format(NOT_LEAF_NODE, path));
-    }
-    return cur;
-  }
-
-  private MNode getLeafByPathWithCheck(MNode node, String path) throws PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length < 1 || !node.hasChild(nodes[0])) {
-      throw new PathErrorException(String.format(SERIES_NOT_CORRECT, path));
-    }
-
-    MNode cur = node.getChild(nodes[0]);
-    for (int i = 1; i < nodes.length; i++) {
-      if (!cur.hasChild(nodes[i])) {
-        throw new PathErrorException(
-                String.format(NO_CHILD_ERROR, cur.getName(), nodes[i]));
-      }
-      cur = cur.getChild(nodes[i]);
-    }
-    if (!cur.isLeaf()) {
-      throw new PathErrorException(String.format(NOT_LEAF_NODE, path));
-    }
-    return cur;
-  }
-
-  private MNode getLeafByPathWithCheck(String path) throws PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length < 2 || !nodes[0].equals(getRoot().getName())) {
-      throw new PathErrorException(String.format(SERIES_NOT_CORRECT, path));
-    }
-
-    MNode cur = getRoot();
-    for (int i = 1; i < nodes.length; i++) {
-      if (!cur.hasChild(nodes[i])) {
-        throw new PathErrorException(
-                String.format(NO_CHILD_ERROR, cur.getName(), nodes[i]));
-      }
-      cur = cur.getChild(nodes[i]);
-    }
-    if (!cur.isLeaf()) {
-      throw new PathErrorException(String.format(NOT_LEAF_NODE, path));
-    }
-    return cur;
+    return lastNode;
   }
 
   /**
-   * function for getting node by path with file level check.
+   * function for getting a node by path in a storage group. PathErrorException will rise if the
+   * path does not belong to a storage group.
    */
-  MNode getNodeByPathWithStorageGroupCheck(String path) throws PathErrorException, StorageGroupException {
+  MNode getNodeInStorageGroup(String path) throws PathErrorException {
     boolean storageGroupChecked = false;
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodes = MetaUtils.getNodeNames(path);
     if (nodes.length < 2 || !nodes[0].equals(getRoot().getName())) {
       throw new PathErrorException(String.format(SERIES_NOT_CORRECT, path));
     }
@@ -423,7 +357,7 @@ public class MTree implements Serializable {
     for (int i = 1; i < nodes.length; i++) {
       if (!cur.hasChild(nodes[i])) {
         if (!storageGroupChecked) {
-          throw new StorageGroupException("Storage group is not set for current seriesPath:" + path);
+          throw new PathErrorException("Storage group is not set for current seriesPath:" + path);
         }
         throw new PathErrorException(String.format(NO_CHILD_ERROR, cur.getName(), nodes[i]));
       }
@@ -435,7 +369,7 @@ public class MTree implements Serializable {
     }
 
     if (!storageGroupChecked) {
-      throw new StorageGroupException("Storage group is not set for current seriesPath:" + path);
+      throw new PathErrorException("Storage group is not set for current seriesPath:" + path);
     }
     return cur;
   }
@@ -446,7 +380,7 @@ public class MTree implements Serializable {
    * @return last node in given seriesPath
    */
   MNode getNode(String path) throws PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodes = MetaUtils.getNodeNames(path);
     if (nodes.length < 2 || !nodes[0].equals(getRoot().getName())) {
       throw new PathErrorException(String.format(SERIES_NOT_CORRECT, path));
     }
@@ -461,7 +395,7 @@ public class MTree implements Serializable {
   }
 
   private void checkPath(MNode node, String path) throws PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodes = MetaUtils.getNodeNames(path);
     if (nodes.length < 1) {
       return;
     }
@@ -481,7 +415,12 @@ public class MTree implements Serializable {
    * @return String storage group seriesPath
    */
   String getStorageGroupNameByPath(String path) throws StorageGroupException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodes;
+    try {
+      nodes = MetaUtils.getNodeNames(path);
+    } catch (PathErrorException e) {
+      throw new StorageGroupException(e);
+    }
     MNode cur = getRoot();
     for (int i = 1; i < nodes.length; i++) {
       if (cur == null) {
@@ -506,7 +445,7 @@ public class MTree implements Serializable {
    */
   List<String> getAllFileNamesByPath(String pathReg) throws PathErrorException {
     ArrayList<String> fileNames = new ArrayList<>();
-    String[] nodes = MetaUtils.getNodeNames(pathReg, PATH_SEPARATOR);
+    String[] nodes = MetaUtils.getNodeNames(pathReg);
     if (nodes.length == 0 || !nodes[0].equals(getRoot().getName())) {
       throw new PathErrorException(String.format(SERIES_NOT_CORRECT, pathReg));
     }
@@ -547,7 +486,12 @@ public class MTree implements Serializable {
    * function for getting file name by path.
    */
   String getStorageGroupNameByPath(MNode node, String path) throws StorageGroupException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodes;
+    try {
+      nodes = MetaUtils.getNodeNames(path);
+    } catch (PathErrorException e) {
+      throw new StorageGroupException(e);
+    }
     MNode cur = node.getChild(nodes[0]);
     for (int i = 1; i < nodes.length; i++) {
       if (cur == null) {
@@ -571,7 +515,7 @@ public class MTree implements Serializable {
    * seriesPath is not storage group seriesPath
    */
   boolean checkFileNameByPath(String path) {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodes = path.split(PATH_SEPARATOR_NO_REGEX);
     MNode cur = getRoot();
     for (int i = 1; i <= nodes.length; i++) {
       if (cur == null) {
@@ -592,10 +536,15 @@ public class MTree implements Serializable {
    * @return A HashMap whose Keys are separated by the storage file name.
    */
   HashMap<String, List<String>> getAllPath(String pathReg) throws PathErrorException {
+    String[] nodes = MetaUtils.getNodeNames(pathReg);
+    return getAllPath(nodes);
+  }
+
+  HashMap<String, List<String>> getAllPath(String[] nodes) throws PathErrorException {
     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 PathErrorException(String.format(SERIES_NOT_CORRECT, pathReg));
+      throw new PathErrorException(String.format(SERIES_NOT_CORRECT, String.join(PATH_SEPARATOR,
+       nodes)));
     }
     findPath(getRoot(), nodes, 1, "", paths);
     return paths;
@@ -608,7 +557,7 @@ public class MTree implements Serializable {
    */
   List<MNode> getAllStorageGroupNodes() {
     List<MNode> ret = new ArrayList<>();
-    Stack<MNode> nodeStack = new Stack<>();
+    Deque<MNode> nodeStack = new ArrayDeque<>();
     nodeStack.add(getRoot());
     while (!nodeStack.isEmpty()) {
       MNode current = nodeStack.pop();
@@ -623,14 +572,16 @@ public class MTree implements Serializable {
 
   /**
    * function for getting all timeseries paths under the given seriesPath.
+   * @return each list in the returned list consists of 4 strings: full path, storage group, data
+   * type and encoding of a timeseries
    */
-  List<List<String>> getShowTimeseriesPath(String pathReg) throws PathErrorException {
+  List<List<String>> getTimeseriesInfo(String[] nodes) throws PathErrorException {
     List<List<String>> res = new ArrayList<>();
-    String[] nodes = MetaUtils.getNodeNames(pathReg, PATH_SEPARATOR);
     if (nodes.length == 0 || !nodes[0].equals(getRoot().getName())) {
-      throw new PathErrorException(String.format(SERIES_NOT_CORRECT, pathReg));
+      throw new PathErrorException(String.format(SERIES_NOT_CORRECT, String.join(PATH_SEPARATOR,
+       nodes)));
     }
-    findPath(getRoot(), nodes, 1, "", res);
+    retrieveTimeseriesInfo(getRoot(), nodes, 1, "", res);
     return res;
   }
 
@@ -663,49 +614,6 @@ public class MTree implements Serializable {
   }
 
   /**
-   * Calculate the count of storage-level nodes included in given seriesPath.
-   *
-   * @return The total count of storage-level nodes.
-   */
-  int getFileCountForOneType(String path) throws PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length != 2 || !nodes[0].equals(getRoot().getName()) || !getRoot()
-            .hasChild(nodes[1])) {
-      throw new PathErrorException(
-              "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);
-      }
-    }
-    return sum;
-  }
-
-  /**
-   * Get all device type in current Metadata Tree.
-   *
-   * @return a list contains all distinct device type
-   */
-  ArrayList<String> getAllType() {
-    ArrayList<String> res = new ArrayList<>();
-    if (getRoot() != null) {
-      res.addAll(getRoot().getChildren().keySet());
-    }
-    return res;
-  }
-
-  /**
    * Get all storage groups in current Metadata Tree.
    *
    * @return a list contains all distinct storage groups
@@ -734,30 +642,27 @@ public class MTree implements Serializable {
    *
    * @return a list contains all distinct devices
    */
-  Set<String> getAllDevices() {
-    HashSet<String> devices = new HashSet<>();
-    MNode node;
-    if ((node = getRoot()) != null) {
-      findDevices(node, SQLConstant.ROOT, devices);
-    }
-    return new LinkedHashSet<>(devices);
-  }
+  List<String> getAllDevices() {
+    List<String> devices = new ArrayList<>();
+    Deque<MNode> nodeStack = new ArrayDeque<>();
+    nodeStack.addLast(root);
 
-  private void findDevices(MNode node, String path, HashSet<String> res) {
-    if (node == null) {
-      return;
-    }
-    if (node.isLeaf()) {
-      res.add(path);
-      return;
-    }
-    for (MNode child : node.getChildren().values()) {
-      if (child.isLeaf()) {
-        res.add(path);
-      } else {
-        findDevices(child, path + "." + child.toString(), res);
+    while (!nodeStack.isEmpty()) {
+      MNode current = nodeStack.removeFirst();
+      boolean currentAdded = false;
+      if (current.hasChildren()) {
+        for (MNode child : current.getChildren().values()) {
+          if (child.isLeaf() && !currentAdded) {
+            devices.add(current.getFullPath());
+            currentAdded = true;
+          } else if (!child.isLeaf()) {
+            nodeStack.addLast(child);
+          }
+        }
       }
     }
+
+    return devices;
   }
 
   /**
@@ -765,40 +670,54 @@ public class MTree implements Serializable {
    *
    * @return a list contains all nodes at the given level
    */
-  List<String> getNodesList(String schemaPattern, int nodeLevel) throws SQLException {
-    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]);
-          }
+  List<String> getNodesList(String prefixPath, int nodeLevel) throws SQLException {
+    String[] nodes = prefixPath.split(PATH_SEPARATOR_NO_REGEX);
+
+    if (nodes[0].equals(IoTDBConstant.PATH_ROOT)) {
+      MNode node = getRoot();
+      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));
-      } else {
-        throw new SQLException("Incorrect root node " + nodes[0] + " selected");
       }
+      return findNodes(node, prefixPath, nodeLevel - (nodes.length - 1));
+    } else {
+      throw new SQLException("Incorrect root node " + nodes[0] + " selected");
     }
-    return res;
   }
 
-  private void findNodes(MNode node, String path, List<String> res, int targetLevel) {
-    if (node == null) {
-      return;
-    }
-    if (targetLevel == 0) {
-      res.add(path);
-      return;
-    }
-    if (node.hasChildren()) {
-      for (MNode child : node.getChildren().values()) {
-        findNodes(child, path + "." + child.toString(), res, targetLevel - 1);
+  private List<String> findNodes(MNode node, String path, int targetLevel) {
+    List<String> res = new ArrayList<>();
+
+    Deque<MNode> nodeStack = new ArrayDeque<>();
+    nodeStack.addLast(node);
+
+    int currLevelCnt = 1;
+    int nextLevelCnt = 0;
+    while (targetLevel > 0) {
+      MNode current = nodeStack.removeFirst();
+      currLevelCnt--;
+      if (current.hasChildren()) {
+        for (MNode child : current.getChildren().values()) {
+          nodeStack.addLast(child);
+          // these children are added to the next level
+          nextLevelCnt++;
+        }
+      }
+      if (currLevelCnt == 0) {
+        // current level has exhausted, start the next level
+        targetLevel--;
+        currLevelCnt = nextLevelCnt;
+        nextLevelCnt = 0;
       }
     }
+
+    while (!nodeStack.isEmpty()) {
+      res.add(nodeStack.removeFirst().getFullPath());
+    }
+    return res;
   }
 
   /**
@@ -828,31 +747,12 @@ public class MTree implements Serializable {
   }
 
   /**
-   * 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 PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
-    if (nodes.length != 2 || !nodes[0].equals(getRoot().getName()) || !getRoot()
-            .hasChild(nodes[1])) {
-      throw new PathErrorException(
-              "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.
    *
    * @return ArrayList<ColumnSchema> The list of the schema
    */
-  ArrayList<MeasurementSchema> getSchemaForOneStorageGroup(String path) {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+  List<MeasurementSchema> getSchemaForOneStorageGroup(String path) {
+    String[] nodes = path.split(PATH_SEPARATOR_NO_REGEX);
     HashMap<String, MeasurementSchema> leafMap = new HashMap<>();
     MNode cur = getRoot();
     for (int i = 1; i < nodes.length; i++) {
@@ -867,7 +767,7 @@ public class MTree implements Serializable {
    * function for getting schema map for one storage group.
    */
   Map<String, MeasurementSchema> getSchemaMapForOneStorageGroup(String path) {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodes = path.split(PATH_SEPARATOR_NO_REGEX);
     MNode cur = getRoot();
     for (int i = 1; i < nodes.length; i++) {
       cur = cur.getChild(nodes[i]);
@@ -879,7 +779,7 @@ public class MTree implements Serializable {
    * function for getting num schema map for one file node.
    */
   Map<String, Integer> getNumSchemaMapForOneFileNode(String path) {
-    String[] nodes = MetaUtils.getNodeNames(path, PATH_SEPARATOR);
+    String[] nodes = path.split(PATH_SEPARATOR_NO_REGEX);
     MNode cur = getRoot();
     for (int i = 1; i < nodes.length; i++) {
       cur = cur.getChild(nodes[i]);
@@ -905,7 +805,7 @@ public class MTree implements Serializable {
       if (nodes.length <= idx) {
         String fileName = node.getDataFileName();
         String nodeName;
-        if (node.getName().contains(TsFileConstant.PATH_SEPARATOR)) {
+        if (node.getName().contains(PATH_SEPARATOR)) {
           nodeName = "\"" + node + "\"";
         } else {
           nodeName = "" + node;
@@ -935,8 +835,10 @@ public class MTree implements Serializable {
 
   /*
    * Iterate through MTree to fetch metadata info of all leaf nodes under the given seriesPath
+   * the full path,storage group,resultDataType,encoding of each timeseries will be put into a
+   * list and the list will be added into res
    */
-  private void findPath(MNode node, String[] nodes, int idx, String parent,
+  private void retrieveTimeseriesInfo(MNode node, String[] nodes, int idx, String parent,
                         List<List<String>> res) {
     if (node.isLeaf()) {
       if (nodes.length <= idx) {
@@ -960,11 +862,11 @@ public class MTree implements Serializable {
 
     if (!("*").equals(nodeReg)) {
       if (node.hasChild(nodeReg)) {
-        findPath(node.getChild(nodeReg), nodes, idx + 1, parent + node.getName() + ".", res);
+        retrieveTimeseriesInfo(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);
+        retrieveTimeseriesInfo(child, nodes, idx + 1, parent + node.getName() + ".", res);
       }
     }
   }
@@ -982,12 +884,9 @@ public class MTree implements Serializable {
 
   @Override
   public String toString() {
-    return jsonToString(toJson());
+    return SchemaUtils.jsonToString(toJson());
   }
 
-  private static String jsonToString(JSONObject jsonObject) {
-    return JSON.toJSONString(jsonObject, SerializerFeature.PrettyFormat);
-  }
 
   private JSONObject toJson() {
     JSONObject jsonObject = new JSONObject();
@@ -1015,46 +914,4 @@ public class MTree implements Serializable {
     return root;
   }
 
-  /**
-   * combine multiple metadata in string format
-   */
-  static String combineMetadataInStrings(String[] metadataStrs) {
-    JSONObject[] jsonObjects = new JSONObject[metadataStrs.length];
-    for (int i = 0; i < jsonObjects.length; i++) {
-      jsonObjects[i] = JSONObject.parseObject(metadataStrs[i]);
-    }
-
-    JSONObject root = jsonObjects[0];
-    for (int i = 1; i < jsonObjects.length; i++) {
-      root = combineJSONObjects(root, jsonObjects[i]);
-    }
-    return jsonToString(root);
-  }
-
-  private static JSONObject combineJSONObjects(JSONObject a, JSONObject b) {
-    JSONObject res = new JSONObject();
-
-    Set<String> retainSet = new HashSet<>(a.keySet());
-    retainSet.retainAll(b.keySet());
-    Set<String> aCha = new HashSet<>(a.keySet());
-    Set<String> bCha = new HashSet<>(b.keySet());
-    aCha.removeAll(retainSet);
-    bCha.removeAll(retainSet);
-    for (String key : aCha) {
-      res.put(key, a.getJSONObject(key));
-    }
-    for (String key : bCha) {
-      res.put(key, b.get(key));
-    }
-    for (String key : retainSet) {
-      Object v1 = a.get(key);
-      Object v2 = b.get(key);
-      if (v1 instanceof JSONObject && v2 instanceof JSONObject) {
-        res.put(key, combineJSONObjects((JSONObject) v1, (JSONObject) v2));
-      } else {
-        res.put(key, v1);
-      }
-    }
-    return res;
-  }
 }
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..0dc1ac2 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,69 @@
  */
 package org.apache.iotdb.db.metadata;
 
-public class MetaUtils {
-  public static String[] getNodeNames(String path, String separator) {
-    String[] nodeNames;
+import static org.apache.iotdb.tsfile.common.constant.TsFileConstant.PATH_SEPARATOR_NO_REGEX;
+
+import org.apache.iotdb.db.exception.PathErrorException;
+
+class MetaUtils {
+
+  private MetaUtils() {
+    // util class
+  }
+
+  static String[] getNodeNames(String path) throws PathErrorException {
     path = path.trim();
-    if (path.contains("\"") || path.contains("\'")) {
-      String[] deviceAndMeasurement;
-      if (path.contains("\"")) {
-        deviceAndMeasurement = path.split("\"");
-      } else {
-        deviceAndMeasurement = path.split("\'");
+
+    int firstSingleQuotePos = -1;
+    int firstDoubleQuotePos = -1;
+    for (int i = 0; i < path.length(); i++) {
+      if (firstSingleQuotePos == -1 && path.charAt(i) == '\'') {
+        firstSingleQuotePos = i;
+      }
+      if (firstDoubleQuotePos == -1 && path.charAt(i) == '\"') {
+        firstDoubleQuotePos = i;
       }
-      String device = deviceAndMeasurement[0];
-      String measurement = deviceAndMeasurement[1];
-      String[] deviceNodeName = device.split(separator);
-      int nodeNumber = deviceNodeName.length + 1;
+    }
+
+    if (firstDoubleQuotePos != -1 && firstSingleQuotePos != -1) {
+      throw new PathErrorException("Path contains both \" and \': " + path);
+    }
+
+    return getNodeNames(path, firstSingleQuotePos, firstDoubleQuotePos);
+  }
+
+  private static String[] getNodeNames(String path, int firstSingleQuotePos,
+      int firstDoubleQuotePos) throws PathErrorException {
+    String[] nodeNames;
+
+    if (firstSingleQuotePos != -1 && path.charAt(path.length() - 1) != '\'' ||
+        firstDoubleQuotePos != -1 && path.charAt(path.length() - 1) != '\"') {
+      throw new PathErrorException("Path contains but not ends with \' or \": " + path);
+    } else if (firstDoubleQuotePos == -1 && firstSingleQuotePos == -1) {
+      return path.split(PATH_SEPARATOR_NO_REGEX);
+    }
+
+    String device = null;
+    String measurement;
+    int quotePos = firstDoubleQuotePos != -1 ? firstDoubleQuotePos :
+        firstSingleQuotePos;
+    if (quotePos == 0) {
+      measurement = path;
+    } else {
+      device = path.substring(0, quotePos - 1);
+      measurement = path.substring(quotePos + 1, path.length() - 1);
+    }
+
+    if (device == null) {
+      nodeNames = new String[]{measurement};
+    } else {
+      String[] deviceNodeNames = device.split(PATH_SEPARATOR_NO_REGEX);
+      int nodeNumber = deviceNodeNames.length + 1;
       nodeNames = new String[nodeNumber];
-      System.arraycopy(deviceNodeName, 0, nodeNames, 0, nodeNumber - 1);
+      System.arraycopy(deviceNodeNames, 0, nodeNames, 0, nodeNumber - 1);
       nodeNames[nodeNumber - 1] = measurement;
-    } else {
-      nodeNames = path.split(separator);
     }
+
     return nodeNames;
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/Metadata.java b/server/src/main/java/org/apache/iotdb/db/metadata/Metadata.java
deleted file mode 100644
index ee59a2a..0000000
--- a/server/src/main/java/org/apache/iotdb/db/metadata/Metadata.java
+++ /dev/null
@@ -1,125 +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.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * This class stores all the metadata info for every deviceId and every timeseries.
- */
-public class Metadata implements Serializable {
-
-  private Map<String, List<String>> deviceIdMap;
-
-  public Metadata(Map<String, List<String>> deviceIdMap) {
-    this.deviceIdMap = deviceIdMap;
-  }
-
-  public Map<String, List<String>> getDeviceMap() {
-    return deviceIdMap;
-  }
-
-  /**
-   * combine multiple metadatas
-   */
-  public static Metadata combineMetadatas(Metadata[] metadatas) {
-    Map<String, List<String>> deviceIdMap = new HashMap<>();
-
-    if (metadatas == null || metadatas.length == 0) {
-      return new Metadata(deviceIdMap);
-    }
-
-    for (int i = 0; i < metadatas.length; i++) {
-      Map<String, List<String>> subDeviceIdMap = metadatas[i].deviceIdMap;
-      for (Entry<String, List<String>> entry : subDeviceIdMap.entrySet()) {
-        List<String> list = deviceIdMap.getOrDefault(entry.getKey(), new ArrayList<>());
-        list.addAll(entry.getValue());
-
-        if (!deviceIdMap.containsKey(entry.getKey())) {
-          deviceIdMap.put(entry.getKey(), list);
-        }
-      }
-      metadatas[i] = null;
-    }
-
-    return new Metadata(deviceIdMap);
-  }
-
-  @Override
-  public String toString() {
-    return deviceIdMap.toString();
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    if(this == obj){
-      return true;
-    }
-    if(obj == null){
-      return false;
-    }
-    if(this.getClass() != obj.getClass()){
-      return false;
-    }
-
-    Metadata metadata = (Metadata) obj;
-    return deviceIdMapEquals(deviceIdMap, metadata.deviceIdMap);
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(deviceIdMap);
-  }
-
-  /**
-   * only used to check if deviceIdMap is equal to another deviceIdMap
-   */
-  private boolean deviceIdMapEquals(Map<String, List<String>> map1, Map<String, List<String>> map2) {
-    if (!map1.keySet().equals(map2.keySet())) {
-      return false;
-    }
-
-    for (Entry<String, List<String>> entry : map1.entrySet()) {
-      List list1 = entry.getValue();
-      List list2 = map2.get(entry.getKey());
-
-      if (!listEquals(list1, list2)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  private boolean listEquals(List list1, List list2) {
-    Set set1 = new HashSet();
-    set1.addAll(list1);
-    Set set2 = new HashSet();
-    set2.addAll(list2);
-
-    return set1.equals(set2);
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java b/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java
deleted file mode 100644
index 13bb74f..0000000
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MetadataConstant.java
+++ /dev/null
@@ -1,27 +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;
-
-public class MetadataConstant {
-  private MetadataConstant(){
-    //allowed to do nothing
-  }
-  public static final String ROOT = "root";
-  public static final String METADATA_LOG = "mlog.txt";
-}
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..4b8574e 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,16 @@ 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";
+  static final String ADD_PATH_TO_MTREE = "0";
+  static final String DELETE_PATH_FROM_MTREE = "1";
+  static final String SET_STORAGE_GROUP_TO_MTREE = "2";
+  static final String ADD_A_PTREE = "3";
+  static final String ADD_A_PATH_TO_PTREE = "4";
+  static final String DELETE_PATH_FROM_PTREE = "5";
+  static final String LINK_MNODE_TO_PTREE = "6";
+  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 SET_TTL = "10";
-  public static final String DELETE_STORAGE_GROUP_FROM_MTREE = "11";
+  static final String SET_TTL = "10";
+  static final String DELETE_STORAGE_GROUP_FROM_MTREE = "11";
 }
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
index 1faf3c5..32faa5a 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/PTree.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/PTree.java
@@ -18,6 +18,8 @@
  */
 package org.apache.iotdb.db.metadata;
 
+import static org.apache.iotdb.tsfile.common.constant.TsFileConstant.PATH_SEPARATOR;
+
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -45,17 +47,12 @@ public class PTree implements Serializable {
   /**
    * Add a seriesPath to current PTree
    *
-   * @return The count of new added {@code PNode} TODO: unused
    * @throws PathErrorException
    */
-  int addPath(String path) throws PathErrorException {
-    int addCount = 0;
-    if (getRoot() == null) {
-      throw new PathErrorException("Root Node is null, Please initialize root first");
-    }
-    String[] nodes = MetaUtils.getNodeNames(path, "\\.");
+  void addPath(String[] nodes) throws PathErrorException {
     if (nodes.length <= 1 || !nodes[0].equals(getRoot().getName())) {
-      throw new PathErrorException("Input seriesPath not exist. Path: " + path);
+      throw new PathErrorException("Input seriesPath not exist. Path: "
+          + String.join(PATH_SEPARATOR, nodes));
     }
 
     PNode cur = getRoot();
@@ -63,18 +60,16 @@ public class PTree implements Serializable {
     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 PathErrorException("Path already exists. Path: " + path);
+      throw new PathErrorException("Path already exists. Path: "
+          + String.join(PATH_SEPARATOR, nodes));
     } else {
       PNode node = new PNode(nodes[i], cur, true);
       cur.addChild(node.getName(), node);
-      addCount++;
     }
-    return addCount;
   }
 
   /**
@@ -83,7 +78,7 @@ public class PTree implements Serializable {
    * @throws PathErrorException
    */
   void deletePath(String path) throws PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, "\\.");
+    String[] nodes = MetaUtils.getNodeNames(path);
     if (nodes.length == 0 || !nodes[0].equals(getRoot().getName())) {
       throw new PathErrorException("Path not correct. Path:" + path);
     }
@@ -103,10 +98,9 @@ public class PTree implements Serializable {
    *
    * @throws PathErrorException
    */
-  void linkMNode(String pTreePath, String mTreePath) throws PathErrorException {
+  void linkMNode(String[] pTreeNodes, String mTreePath) throws PathErrorException {
     List<String> paths = mTree.getAllPathInList(mTreePath);
-    String[] nodes = MetaUtils.getNodeNames(pTreePath, "\\.");
-    PNode leaf = getLeaf(getRoot(), nodes, 0);
+    PNode leaf = getLeaf(getRoot(), pTreeNodes, 0);
     for (String p : paths) {
       leaf.linkMPath(p);
     }
@@ -117,10 +111,9 @@ public class PTree implements Serializable {
    *
    * @throws PathErrorException
    */
-  void unlinkMNode(String pTreePath, String mTreePath) throws PathErrorException {
+  void unlinkMNode(String[] pTreeNodes, String mTreePath) throws PathErrorException {
     List<String> paths = mTree.getAllPathInList(mTreePath);
-    String[] nodes = MetaUtils.getNodeNames(pTreePath, "\\.");
-    PNode leaf = getLeaf(getRoot(), nodes, 0);
+    PNode leaf = getLeaf(getRoot(), pTreeNodes, 0);
     for (String p : paths) {
       leaf.unlinkMPath(p);
     }
@@ -153,7 +146,7 @@ public class PTree implements Serializable {
    */
   HashMap<String, List<String>> getAllLinkedPath(String path)
       throws PathErrorException {
-    String[] nodes = MetaUtils.getNodeNames(path, "\\.");
+    String[] nodes = MetaUtils.getNodeNames(path);
     PNode leaf = getLeaf(getRoot(), nodes, 0);
     HashMap<String, List<String>> res = new HashMap<>();
 
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 11f1d0b..07c7fd9 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
@@ -306,24 +306,19 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
     try {
       switch (req.getType()) {
         case "SHOW_TIMESERIES":
-          String path = req.getColumnPath();
-          List<List<String>> timeseriesList = getTimeSeriesForPath(path);
-          resp.setTimeseriesList(timeseriesList);
+          resp.setTimeseriesInfoList(getTimeSeriesInfo(req.getColumnPath()));
           status = new TSStatus(getStatus(TSStatusCode.SUCCESS_STATUS));
           break;
         case "SHOW_STORAGE_GROUP":
-          Set<String> storageGroups = new HashSet<>(getAllStorageGroups());
-          resp.setStorageGroups(storageGroups);
+          resp.setStorageGroups(getAllStorageGroups());
           status = new TSStatus(getStatus(TSStatusCode.SUCCESS_STATUS));
           break;
         case "METADATA_IN_JSON":
-          String metadataInJson = getMetadataInString();
-          resp.setMetadataInJson(metadataInJson);
+          resp.setMetadataInJson(getMetadataInString());
           status = new TSStatus(getStatus(TSStatusCode.SUCCESS_STATUS));
           break;
         case "SHOW_DEVICES":
-          Set<String> devices = getAllDevices();
-          resp.setDevices(devices);
+          resp.setDevices(getAllDevices());
           status = new TSStatus(getStatus(TSStatusCode.SUCCESS_STATUS));
           break;
         case "COLUMN":
@@ -380,13 +375,13 @@ public class TSServiceImpl implements TSIService.Iface, ServerContext {
     return MManager.getInstance().getAllStorageGroupNames();
   }
 
-  private Set<String> getAllDevices() throws SQLException {
+  private List<String> getAllDevices() {
     return MManager.getInstance().getAllDevices();
   }
 
-  private List<List<String>> getTimeSeriesForPath(String path)
+  private List<List<String>> getTimeSeriesInfo(String path)
       throws PathErrorException {
-    return MManager.getInstance().getShowTimeseriesPath(path);
+    return MManager.getInstance().getTimeseriesInfo(path);
   }
 
   private String getMetadataInString() {
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 9401c1a..e1a8dc5 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
@@ -37,7 +37,6 @@ import org.apache.iotdb.db.exception.MetadataErrorException;
 import org.apache.iotdb.db.exception.PathErrorException;
 import org.apache.iotdb.db.exception.SyncDeviceOwnerConflictException;
 import org.apache.iotdb.db.metadata.MManager;
-import org.apache.iotdb.db.metadata.MetadataConstant;
 import org.apache.iotdb.db.sync.conf.SyncConstant;
 import org.apache.iotdb.db.sync.receiver.load.FileLoader;
 import org.apache.iotdb.db.sync.receiver.load.FileLoaderManager;
@@ -222,7 +221,7 @@ public class SyncServiceImpl implements SyncService.Iface {
             .format("MD5 of the sender is differ from MD5 of the receiver of the file %s.",
                 currentFile.get().getAbsolutePath()));
       } else {
-        if (currentFile.get().getName().endsWith(MetadataConstant.METADATA_LOG)) {
+        if (currentFile.get().getName().endsWith(MManager.METADATA_LOG)) {
           loadMetadata();
         } else {
           if (!currentFile.get().getName().endsWith(TsFileResource.RESOURCE_SUFFIX)) {
diff --git a/server/src/main/java/org/apache/iotdb/db/sync/sender/transfer/DataTransferManager.java b/server/src/main/java/org/apache/iotdb/db/sync/sender/transfer/DataTransferManager.java
index 2354305..34963ce 100644
--- a/server/src/main/java/org/apache/iotdb/db/sync/sender/transfer/DataTransferManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/sync/sender/transfer/DataTransferManager.java
@@ -47,7 +47,7 @@ import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.exception.SyncConnectionException;
 import org.apache.iotdb.db.exception.SyncDeviceOwnerConflictException;
-import org.apache.iotdb.db.metadata.MetadataConstant;
+import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.sync.conf.SyncConstant;
 import org.apache.iotdb.db.sync.conf.SyncSenderConfig;
 import org.apache.iotdb.db.sync.conf.SyncSenderDescriptor;
@@ -330,7 +330,7 @@ public class DataTransferManager implements IDataTransferManager {
       return;
     }
     int retryCount = 0;
-    serviceClient.initSyncData(MetadataConstant.METADATA_LOG);
+    serviceClient.initSyncData(MManager.METADATA_LOG);
     while (true) {
       if (retryCount > config.getMaxNumOfSyncFileRetry()) {
         throw new SyncConnectionException(String
@@ -645,7 +645,7 @@ public class DataTransferManager implements IDataTransferManager {
 
   private File getSchemaLogFile() {
     return new File(IoTDBDescriptor.getInstance().getConfig().getSchemaDir(),
-        MetadataConstant.METADATA_LOG);
+        MManager.METADATA_LOG);
   }
 
   private static class InstanceHolder {
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..3444a4f 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
@@ -18,7 +18,12 @@
  */
 package org.apache.iotdb.db.utils;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.tsfile.exception.write.WriteProcessException;
 import org.apache.iotdb.tsfile.write.schema.Schema;
@@ -47,11 +52,58 @@ public class SchemaUtils {
    * @param schemaList the schema of the columns in this file.
    * @return a Schema contains the provided schemas.
    */
-  public static Schema getSchemaFromColumnSchema(List<MeasurementSchema> schemaList) {
+  private static Schema getSchemaFromColumnSchema(List<MeasurementSchema> schemaList) {
     Schema schema = new Schema();
     for (MeasurementSchema measurementSchema : schemaList) {
       schema.registerMeasurement(measurementSchema);
     }
     return schema;
   }
+
+  /**
+   * combine multiple metadata in string format
+   */
+  public static String combineMetadataInStrings(String[] metadataStrs) {
+    JSONObject[] jsonObjects = new JSONObject[metadataStrs.length];
+    for (int i = 0; i < jsonObjects.length; i++) {
+      jsonObjects[i] = JSONObject.parseObject(metadataStrs[i]);
+    }
+
+    JSONObject root = jsonObjects[0];
+    for (int i = 1; i < jsonObjects.length; i++) {
+      root = combineJSONObjects(root, jsonObjects[i]);
+    }
+    return jsonToString(root);
+  }
+
+  public static String jsonToString(JSONObject jsonObject) {
+    return JSON.toJSONString(jsonObject, SerializerFeature.PrettyFormat);
+  }
+
+  private static JSONObject combineJSONObjects(JSONObject a, JSONObject b) {
+    JSONObject res = new JSONObject();
+
+    Set<String> retainSet = new HashSet<>(a.keySet());
+    retainSet.retainAll(b.keySet());
+    Set<String> aCha = new HashSet<>(a.keySet());
+    Set<String> bCha = new HashSet<>(b.keySet());
+    aCha.removeAll(retainSet);
+    bCha.removeAll(retainSet);
+    for (String key : aCha) {
+      res.put(key, a.getJSONObject(key));
+    }
+    for (String key : bCha) {
+      res.put(key, b.get(key));
+    }
+    for (String key : retainSet) {
+      Object v1 = a.get(key);
+      Object v2 = b.get(key);
+      if (v1 instanceof JSONObject && v2 instanceof JSONObject) {
+        res.put(key, combineJSONObjects((JSONObject) v1, (JSONObject) v2));
+      } else {
+        res.put(key, v1);
+      }
+    }
+    return res;
+  }
 }
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 4bcbcc0..b50061b 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
@@ -39,7 +39,6 @@ import org.apache.iotdb.db.exception.PathErrorException;
 import org.apache.iotdb.db.exception.ProcessorException;
 import org.apache.iotdb.db.exception.StartupException;
 import org.apache.iotdb.db.exception.StorageEngineException;
-import org.apache.iotdb.db.exception.StorageGroupException;
 import org.apache.iotdb.db.exception.qp.QueryProcessorException;
 import org.apache.iotdb.db.metadata.MManager;
 import org.apache.iotdb.db.metadata.MNode;
@@ -98,7 +97,7 @@ public class TTLTest {
   }
 
   @Test
-  public void testSetMetaTTL() throws IOException, PathErrorException, StorageGroupException {
+  public void testSetMetaTTL() throws IOException, PathErrorException {
     // exception is expected when setting ttl to a non-exist storage group
     boolean caught = false;
     try {
@@ -110,11 +109,11 @@ public class TTLTest {
 
     // normally set ttl
     MManager.getInstance().setTTL(sg1, ttl);
-    MNode mNode = MManager.getInstance().getNodeByPathWithCheck(sg1);
+    MNode mNode = MManager.getInstance().getNodeInStorageGroup(sg1);
     assertEquals(ttl, mNode.getDataTTL());
 
     // default ttl
-    mNode = MManager.getInstance().getNodeByPathWithCheck(sg2);
+    mNode = MManager.getInstance().getNodeInStorageGroup(sg2);
     assertEquals(Long.MAX_VALUE, mNode.getDataTTL());
   }
 
@@ -282,12 +281,12 @@ public class TTLTest {
     QueryProcessExecutor executor = new QueryProcessExecutor();
     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/integration/IoTDBQuotedPathIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBQuotedPathIT.java
index a2dd289..ba6a8dc 100644
--- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBQuotedPathIT.java
+++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBQuotedPathIT.java
@@ -52,64 +52,64 @@ public class IoTDBQuotedPathIT {
 
   @Test
   public void test() throws SQLException {
-    Connection connection = DriverManager
-            .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root",
-                    "root");
-    Statement statement = connection.createStatement();
+    try (Connection connection = DriverManager
+        .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root",
+            "root");
+        Statement statement = connection.createStatement()) {
+      String[] exp = new String[]{
+          "1509465600000,true",
+          "1509465600001,true",
+          "1509465600002,false",
+          "1509465600003,false"
+      };
+      statement.execute("SET STORAGE GROUP TO root.ln.wf01.wt01");
+      statement.execute("CREATE TIMESERIES root.ln.wf01.wt01.\"status.2.3\" WITH DATATYPE=BOOLEAN, ENCODING=PLAIN");
+      statement.execute("INSERT INTO root.ln.wf01.wt01(timestamp,\"status.2.3\") values(1509465600000,true)");
+      statement.execute("INSERT INTO root.ln.wf01.wt01(timestamp,\'status.2.3\') values(1509465600001,true)");
+      statement.execute("INSERT INTO root.ln.wf01.wt01(timestamp,\"status.2.3\") values(1509465600002,false)");
+      statement.execute("INSERT INTO root.ln.wf01.wt01(timestamp,\'status.2.3\') values(1509465600003,false)");
+      statement.execute("SET STORAGE GROUP TO root.ln.wf01.wt02");
+      statement.execute("CREATE TIMESERIES root.ln.wf01.wt02.\"abd\" WITH DATATYPE=BOOLEAN, ENCODING=PLAIN");
+      statement.execute("CREATE TIMESERIES root.ln.wf01.wt02.\"asf.asd.sdf\" WITH DATATYPE=BOOLEAN, ENCODING=PLAIN");
+      statement.execute("CREATE TIMESERIES root.ln.wf01.wt02.\"asd12\" WITH DATATYPE=BOOLEAN, ENCODING=PLAIN");
+      boolean hasResultSet = statement.execute("SELECT * FROM root.ln.wf01.wt01");
 
-    String[] exp = new String[]{
-            "1509465600000,true",
-            "1509465600001,true",
-            "1509465600002,false",
-            "1509465600003,false"
-    };
-    statement.execute("SET STORAGE GROUP TO root.ln.wf01.wt01");
-    statement.execute("CREATE TIMESERIES root.ln.wf01.wt01.\"status.2.3\" WITH DATATYPE=BOOLEAN, ENCODING=PLAIN");
-    statement.execute("INSERT INTO root.ln.wf01.wt01(timestamp,\"status.2.3\") values(1509465600000,true)");
-    statement.execute("INSERT INTO root.ln.wf01.wt01(timestamp,\'status.2.3\') values(1509465600001,true)");
-    statement.execute("INSERT INTO root.ln.wf01.wt01(timestamp,\"status.2.3\") values(1509465600002,false)");
-    statement.execute("INSERT INTO root.ln.wf01.wt01(timestamp,\'status.2.3\') values(1509465600003,false)");
-    statement.execute("SET STORAGE GROUP TO root.ln.wf01.wt02");
-    statement.execute("CREATE TIMESERIES root.ln.wf01.wt02.\"abd\" WITH DATATYPE=BOOLEAN, ENCODING=PLAIN");
-    statement.execute("CREATE TIMESERIES root.ln.wf01.wt02.\"asf.asd.sdf\" WITH DATATYPE=BOOLEAN, ENCODING=PLAIN");
-    statement.execute("CREATE TIMESERIES root.ln.wf01.wt02.\"asd12\" WITH DATATYPE=BOOLEAN, ENCODING=PLAIN");
-    boolean hasResultSet = statement.execute("SELECT * FROM root.ln.wf01.wt01");
+      assertTrue(hasResultSet);
+      int cnt;
+      ArrayList<String> ans = new ArrayList<>();
+      ResultSet resultSet = statement.getResultSet();
+      cnt = 0;
+      while (resultSet.next()) {
+        String result = resultSet.getString(TIMESTAMP_STR) + "," + resultSet.getString(2);
+        ans.add(result);
+        cnt++;
+      }
 
-    assertTrue(hasResultSet);
-    int cnt;
-    ArrayList<String> ans = new ArrayList<>();
-    ResultSet resultSet = statement.getResultSet();
-    cnt = 0;
-    while (resultSet.next()) {
-      String result = resultSet.getString(TIMESTAMP_STR) + "," + resultSet.getString(2);
-      ans.add(result);
-      cnt++;
-    }
+      for (int i = 0; i < ans.size(); i++) {
+        assertEquals(exp[i], ans.get(i));
+      }
 
-    for (int i = 0; i < ans.size(); i++) {
-      assertEquals(exp[i], ans.get(i));
-    }
+      hasResultSet = statement.execute("SELECT  * FROM root.ln.wf01.wt01 WHERE \'status.2.3\' = false");
+      assertTrue(hasResultSet);
+      exp = new String[]{
+          "1509465600002,false",
+          "1509465600003,false"
+      };
+      ans = new ArrayList<>();
+      resultSet = statement.getResultSet();
+      cnt = 0;
+      while (resultSet.next()) {
+        String result = resultSet.getString(TIMESTAMP_STR) + "," + resultSet.getString(2);
+        ans.add(result);
+        cnt++;
+      }
 
-    hasResultSet = statement.execute("SELECT  * FROM root.ln.wf01.wt01 WHERE \'status.2.3\' = false");
-    assertTrue(hasResultSet);
-    exp = new String[]{
-            "1509465600002,false",
-            "1509465600003,false"
-    };
-    ans = new ArrayList<>();
-    resultSet = statement.getResultSet();
-    cnt = 0;
-    while (resultSet.next()) {
-      String result = resultSet.getString(TIMESTAMP_STR) + "," + resultSet.getString(2);
-      ans.add(result);
-      cnt++;
-    }
+      for (int i = 0; i < exp.length; i++) {
+        assertEquals(exp[i], ans.get(i));
+      }
+      statement.execute("DELETE FROM root.ln.wf01.wt01.\"status.2.3\" WHERE time < 1509465600001");
+      statement.execute("DELETE TIMESERIES root.ln.wf01.wt01.\"status.2.3\"");
 
-    for (int i = 0; i < exp.length; i++) {
-      assertEquals(exp[i], ans.get(i));
     }
-    statement.execute("DELETE FROM root.ln.wf01.wt01.\"status.2.3\" WHERE time < 1509465600001");
-    statement.execute("DELETE TIMESERIES root.ln.wf01.wt01.\"status.2.3\"");
-
   }
 }
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 f7c0f2e..11b54c9 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
@@ -22,6 +22,7 @@ package org.apache.iotdb.db.integration;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.sql.DriverManager;
 import java.sql.ResultSet;
@@ -62,7 +63,7 @@ public class IoTDBTtlIT {
         .getConnection(Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
         Statement statement = connection.createStatement()) {
       try {
-        statement.execute("SET TTL TO root.TTL_SG1 1000");
+        statement.execute("SET TTL TO root.TTL_SG1 1200");
       } catch (SQLException e) {
         assertEquals(TSStatusCode.EXECUTE_STATEMENT_ERROR.getStatusCode(), e.getErrorCode());
       }
@@ -76,6 +77,7 @@ public class IoTDBTtlIT {
       statement.execute("CREATE TIMESERIES root.TTL_SG1.s1 WITH DATATYPE=INT64,ENCODING=PLAIN");
       try {
         statement.execute("SET TTL TO root.TTL_SG1.s1 1000");
+        fail("Exception uncaught");
       } catch (SQLException e) {
         assertEquals(TSStatusCode.NOT_A_STORAGE_GROUP_ERROR.getStatusCode(), e.getErrorCode());
       }
@@ -150,22 +152,22 @@ public class IoTDBTtlIT {
       statement.execute("SET STORAGE GROUP TO root.group2");
 
       String result = doQuery(statement, "SHOW ALL TTL", 2);
-      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", 2);
       assertEquals("root.group1,null\n", result);
 
       statement.execute("SET TTL TO root.group1 10000");
       result = doQuery(statement, "SHOW ALL TTL", 2);
-      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", 2);
       assertEquals("root.group1,10000\n", result);
 
       statement.execute("UNSET TTL TO root.group1");
       result = doQuery(statement, "SHOW ALL TTL", 2);
-      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", 2);
       assertEquals("root.group1,null\n", result);
     }
@@ -196,8 +198,8 @@ public class IoTDBTtlIT {
       statement.execute("SET STORAGE GROUP TO root.group2");
 
       String result = doQuery(statement, "SHOW ALL TTL", 2);
-      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
index cc830ad..fc4bb0b 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/MGraphTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/MGraphTest.java
@@ -20,9 +20,14 @@ package org.apache.iotdb.db.metadata;
 
 import static org.junit.Assert.*;
 
+import java.util.Collections;
 import org.apache.iotdb.db.exception.PathErrorException;
 import org.apache.iotdb.db.exception.StorageGroupException;
 import org.apache.iotdb.db.utils.EnvironmentUtils;
+import org.apache.iotdb.db.utils.SchemaUtils;
+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.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -47,32 +52,42 @@ public class MGraphTest {
     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.addPathToMTree("root.a.d0.s0", TSDataType.INT32, TSEncoding.RLE,
+          CompressionType.UNCOMPRESSED,Collections.emptyMap());
+      root.addPathToMTree("root.a.d0.s1", TSDataType.INT32, TSEncoding.RLE,
+          CompressionType.UNCOMPRESSED,Collections.emptyMap());
 
       root.setStorageGroup("root.a.d1");
-      root.addPathToMTree("root.a.d1.s0", "INT32", "RLE");
-      root.addPathToMTree("root.a.d1.s1", "INT32", "RLE");
+      root.addPathToMTree("root.a.d1.s0", TSDataType.INT32, TSEncoding.RLE,
+          CompressionType.UNCOMPRESSED,Collections.emptyMap());
+      root.addPathToMTree("root.a.d1.s1", TSDataType.INT32, TSEncoding.RLE,
+          CompressionType.UNCOMPRESSED,Collections.emptyMap());
 
       root.setStorageGroup("root.a.b.d0");
-      root.addPathToMTree("root.a.b.d0.s0", "INT32", "RLE");
+      root.addPathToMTree("root.a.b.d0.s0", TSDataType.INT32, TSEncoding.RLE,
+          CompressionType.UNCOMPRESSED,Collections.emptyMap());
 
       root1.setStorageGroup("root.a.d0");
-      root1.addPathToMTree("root.a.d0.s0", "INT32", "RLE");
-      root1.addPathToMTree("root.a.d0.s1", "INT32", "RLE");
+      root1.addPathToMTree("root.a.d0.s0", TSDataType.INT32, TSEncoding.RLE,
+          CompressionType.UNCOMPRESSED,Collections.emptyMap());
+      root1.addPathToMTree("root.a.d0.s1", TSDataType.INT32, TSEncoding.RLE,
+          CompressionType.UNCOMPRESSED,Collections.emptyMap());
 
       root2.setStorageGroup("root.a.d1");
-      root2.addPathToMTree("root.a.d1.s0", "INT32", "RLE");
-      root2.addPathToMTree("root.a.d1.s1", "INT32", "RLE");
+      root2.addPathToMTree("root.a.d1.s0", TSDataType.INT32, TSEncoding.RLE,
+          CompressionType.UNCOMPRESSED,Collections.emptyMap());
+      root2.addPathToMTree("root.a.d1.s1", TSDataType.INT32, TSEncoding.RLE,
+          CompressionType.UNCOMPRESSED,Collections.emptyMap());
 
       root3.setStorageGroup("root.a.b.d0");
-      root3.addPathToMTree("root.a.b.d0.s0", "INT32", "RLE");
+      root3.addPathToMTree("root.a.b.d0.s0", TSDataType.INT32, TSEncoding.RLE,
+          CompressionType.UNCOMPRESSED,Collections.emptyMap());
 
       String[] metadatas = new String[3];
       metadatas[0] = root1.toString();
       metadatas[1] = root2.toString();
       metadatas[2] = root3.toString();
-      assertEquals(MGraph.combineMetadataInStrings(metadatas), root.toString());
+      assertEquals(SchemaUtils.combineMetadataInStrings(metadatas), root.toString());
     } catch (PathErrorException | StorageGroupException e) {
       e.printStackTrace();
       fail(e.getMessage());
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 e34674d..28d629d 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
@@ -114,30 +114,16 @@ public class MManagerAdvancedTest {
     Assert.assertNull(
         mmanager.checkPathStorageGroupAndGetDataType("root.vehicle.d0.s100").getDataType());
 
-    MNode node = mmanager.getNodeByPath("root.vehicle.d0");
+    MNode node = mmanager.getNodeInStorageGroup("root.vehicle.d0");
     Assert.assertEquals(TSDataType.INT32, node.getChild("s0").getSchema().getType());
 
     try {
-      mmanager.getNodeByPath("root.vehicle.d100");
+      mmanager.getNodeInStorageGroup("root.vehicle.d100");
       fail();
     } catch (PathErrorException e) {
       // ignore
     }
   }
 
-  @Test
-  public void testGetNextLevelPath()
-      throws PathErrorException, 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/MManagerImproveTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/MManagerImproveTest.java
index 9e4eead..571b89c 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
@@ -146,39 +146,12 @@ public class MManagerImproveTest {
   }
 
   private void doPathLoopOnceTest(String deviceId, List<String> measurementList)
-      throws PathErrorException, StorageGroupException {
+      throws 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 PathErrorException, 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);
     }
   }
 
@@ -201,15 +174,13 @@ public class MManagerImproveTest {
     } catch (StorageGroupException e) {
       isFileLevelChecked = false;
     }
-    MNode node = mManager.getNodeByPathWithCheck(deviceId);
+    MNode node = mManager.getNodeInStorageGroup(deviceId);
 
     for (String measurement : measurementList) {
       if (!isFileLevelChecked) {
         isFileLevelChecked = mManager.checkFileLevelWithCheck(node, measurement);
       }
       assertTrue(isFileLevelChecked);
-      TSDataType dataType = mManager.getSeriesTypeWithCheck(node, measurement);
-      assertEquals(TSDataType.TEXT, dataType);
     }
   }
 
@@ -255,13 +226,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();
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 465da84..c51f099 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
@@ -30,6 +30,7 @@ import java.util.Map;
 import org.apache.iotdb.db.exception.PathErrorException;
 import org.apache.iotdb.db.exception.StorageGroupException;
 import org.apache.iotdb.db.utils.EnvironmentUtils;
+import org.apache.iotdb.db.utils.SchemaUtils;
 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;
@@ -55,14 +56,16 @@ public class MTreeTest {
   public void testAddLeftNodePath() {
     MTree root = new MTree("root");
     try {
-      root.addTimeseriesPath("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.laptop.d1.s1"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
     } catch (PathErrorException e) {
       e.printStackTrace();
       fail(e.getMessage());
     }
     try {
-      root.addTimeseriesPath("root.laptop.d1.s1.b", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.laptop.d1.s1.b"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
     } catch (PathErrorException e) {
       Assert.assertEquals(
@@ -78,7 +81,8 @@ public class MTreeTest {
     assertTrue(root.isPathExist(path1));
     assertFalse(root.isPathExist("root.laptop.d1"));
     try {
-      root.addTimeseriesPath("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.laptop.d1.s1"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
     } catch (PathErrorException e1) {
       fail(e1.getMessage());
@@ -87,7 +91,8 @@ public class MTreeTest {
     assertTrue(root.isPathExist("root.laptop"));
     assertFalse(root.isPathExist("root.laptop.d1.s2"));
     try {
-      root.addTimeseriesPath("aa.bb.cc", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root.addTimeseriesPath(MetaUtils.getNodeNames("aa.bb.cc"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
     } catch (PathErrorException e) {
       Assert.assertEquals(String.format("Timeseries %s is not right.", "aa.bb.cc"), e.getMessage());
@@ -101,21 +106,26 @@ public class MTreeTest {
       assertFalse(root.isPathExist("root.a.d0"));
       assertFalse(root.checkFileNameByPath("root.a.d0"));
       root.setStorageGroup("root.a.d0");
-      root.addTimeseriesPath("root.a.d0.s0", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root.addTimeseriesPath(MetaUtils.getNodeNames("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
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.a.d0.s1"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
 
       assertFalse(root.isPathExist("root.a.d1"));
       assertFalse(root.checkFileNameByPath("root.a.d1"));
       root.setStorageGroup("root.a.d1");
-      root.addTimeseriesPath("root.a.d1.s0", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root.addTimeseriesPath(MetaUtils.getNodeNames("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
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.a.d1.s1"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (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
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.a.b.d0.s0"),
+          TSDataType.INT32, TSEncoding.RLE,CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
 
     } catch (PathErrorException | StorageGroupException e1) {
@@ -148,42 +158,52 @@ public class MTreeTest {
     MTree root3 = new MTree("root");
     try {
       root.setStorageGroup("root.a.d0");
-      root.addTimeseriesPath("root.a.d0.s0", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root.addTimeseriesPath(MetaUtils.getNodeNames("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
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.a.d0.s1"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
 
       root.setStorageGroup("root.a.d1");
-      root.addTimeseriesPath("root.a.d1.s0", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root.addTimeseriesPath(MetaUtils.getNodeNames("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
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.a.d1.s1"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (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
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.a.b.d0.s0"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
 
       root1.setStorageGroup("root.a.d0");
-      root1.addTimeseriesPath("root.a.d0.s0", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root1.addTimeseriesPath(MetaUtils.getNodeNames("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
+      root1.addTimeseriesPath(MetaUtils.getNodeNames("root.a.d0.s1"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
 
       root2.setStorageGroup("root.a.d1");
-      root2.addTimeseriesPath("root.a.d1.s0", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root2.addTimeseriesPath(MetaUtils.getNodeNames("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
+      root2.addTimeseriesPath(MetaUtils.getNodeNames("root.a.d1.s1"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
 
       root3.setStorageGroup("root.a.b.d0");
-      root3.addTimeseriesPath("root.a.b.d0.s0", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root3.addTimeseriesPath(MetaUtils.getNodeNames("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());
+      assertEquals(SchemaUtils.combineMetadataInStrings(metadataStrs), root.toString());
     } catch (PathErrorException | StorageGroupException e) {
       e.printStackTrace();
       fail(e.getMessage());
@@ -226,16 +246,20 @@ public class MTreeTest {
 
     try {
       assertEquals("root.laptop.d1", root.getStorageGroupNameByPath("root.laptop.d1.s0"));
-      root.addTimeseriesPath("root.laptop.d1.s0", TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
+      root.addTimeseriesPath(MetaUtils.getNodeNames("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
+      root.addTimeseriesPath(MetaUtils.getNodeNames("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
+      root.addTimeseriesPath(MetaUtils.getNodeNames("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
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.laptop.d2.s1"),
+          TSDataType.INT32, TSEncoding.RLE, CompressionType.valueOf
           (TSFileDescriptor.getInstance().getConfig().getCompressor()), Collections.EMPTY_MAP);
     } catch (PathErrorException | StorageGroupException e) {
       e.printStackTrace();
@@ -292,8 +316,10 @@ public class MTreeTest {
     try {
       root.setStorageGroup("root.laptop.d1");
       root.setStorageGroup("root.laptop.d2");
-      root.addTimeseriesPath("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN, CompressionType.GZIP, null);
-      root.addTimeseriesPath("root.laptop.d1.s1", TSDataType.INT32, TSEncoding.PLAIN, CompressionType.GZIP, null);
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.laptop.d1.s1"),
+          TSDataType.INT32, TSEncoding.PLAIN, CompressionType.GZIP, null);
+      root.addTimeseriesPath(MetaUtils.getNodeNames("root.laptop.d1.s1"),
+          TSDataType.INT32, TSEncoding.PLAIN, CompressionType.GZIP, null);
 
       List<String> list = new ArrayList<>();
 
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 3d21e65..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.MetadataErrorException;
-import org.apache.iotdb.db.exception.PathErrorException;
-import org.apache.iotdb.db.exception.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 (PathErrorException | IOException | MetadataErrorException | StorageGroupException e) {
-      e.printStackTrace();
-      fail(e.getMessage());
-    }
-  }
-}
\ No newline at end of file
diff --git a/service-rpc/rpc-changelist.md b/service-rpc/rpc-changelist.md
index c66a7c4..56abce7 100644
--- a/service-rpc/rpc-changelist.md
+++ b/service-rpc/rpc-changelist.md
@@ -72,6 +72,7 @@ Last Updated on October 27th, 2019 by Lei Rui.
 | Rename some fields in TSFetchMetadataResp: ~~ColumnsList~~ to columnsList, ~~showTimeseriesList~~ to timeseriesList, ~~showStorageGroups~~ to storageGroups | Zesong Sun             |
 | Change struct TSQueryDataSet to eliminate row-wise rpc writing | Lei Rui                |
 | Add optional i32 timeseriesNum in TSFetchMetadataResp        | Jack Tsai              |
-
+| Rename timeseriesList in TSFetchMetadataResp to timeseriesInfoList          | Tian Jiang   |
+| Change the type of devices and storageGroups in TSFetchMetadataResp to List | Tian Jiang   |
 
 
diff --git a/service-rpc/src/main/thrift/rpc.thrift b/service-rpc/src/main/thrift/rpc.thrift
index 0e1186f..03681f2 100644
--- a/service-rpc/src/main/thrift/rpc.thrift
+++ b/service-rpc/src/main/thrift/rpc.thrift
@@ -179,9 +179,10 @@ struct TSFetchMetadataResp{
 		3: optional list<string> columnsList
 		4: optional i32 timeseriesNum
 		5: optional string dataType
-		6: optional list<list<string>> timeseriesList
-		7: optional set<string> storageGroups
-		8: optional set<string> devices
+		// each list contains the full path, storage group, data type and encoding of a timeseries
+		6: optional list<list<string>> timeseriesInfoList
+		7: optional list<string> storageGroups
+		8: optional list<string> devices
 		9: optional list<string> nodesList
 		10: optional map<string, string> nodeTimeseriesNum
 }
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/common/constant/TsFileConstant.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/common/constant/TsFileConstant.java
index 479bd8e..cbe190c 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/common/constant/TsFileConstant.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/common/constant/TsFileConstant.java
@@ -25,7 +25,7 @@ public class TsFileConstant {
   public static final String TSFILE_CONF = "TSFILE_CONF";
   public static final String PATH_ROOT = "root";
   public static final String PATH_SEPARATOR = ".";
-  public static final String PATH_SEPARATER_NO_REGEX = "\\.";
+  public static final String PATH_SEPARATOR_NO_REGEX = "\\.";
   public static final String DEFAULT_DELTA_TYPE = "default_delta_type";
 
   private TsFileConstant(){}
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/Path.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/Path.java
index c91b75e..feb65d1 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/Path.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/read/common/Path.java
@@ -110,7 +110,7 @@ public class Path implements Serializable {
       measurement = subStrs[1];
       fullPath = pathSc;
     } else {
-      StringContainer sc = new StringContainer(pathSc.split(TsFileConstant.PATH_SEPARATER_NO_REGEX), TsFileConstant.PATH_SEPARATOR);
+      StringContainer sc = new StringContainer(pathSc.split(TsFileConstant.PATH_SEPARATOR_NO_REGEX), TsFileConstant.PATH_SEPARATOR);
       if (sc.size() <= 1) {
         device = "";
         fullPath = measurement = sc.toString();