You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by zy...@apache.org on 2023/03/06 08:35:54 UTC

[iotdb] branch master updated: [IOTDB-5621] Eliminate the deprecated code in the template (#9219)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 8bf40931bf [IOTDB-5621] Eliminate the deprecated code in the template (#9219)
8bf40931bf is described below

commit 8bf40931bf33ce11d7156e801d2fa70334486a62
Author: Chen YZ <43...@users.noreply.github.com>
AuthorDate: Mon Mar 6 16:35:48 2023 +0800

    [IOTDB-5621] Eliminate the deprecated code in the template (#9219)
---
 .../request/ConfigPhysicalPlanSerDeTest.java       |  20 +-
 .../persistence/ClusterSchemaInfoTest.java         |  21 +-
 .../confignode/persistence/TemplateTableTest.java  |  36 +--
 .../impl/DeactivateTemplateProcedureTest.java      |   4 +-
 .../procedure/impl/UnsetTemplateProcedureTest.java |   2 +-
 .../iotdb/db/it/schema/IoTDBSchemaTemplateIT.java  |  19 +-
 .../db/integration/IoTDBSchemaTemplateIT.java      | 357 ---------------------
 .../mnode/iterator/AbstractTraverserIterator.java  |   3 +-
 .../db/metadata/mtree/traverser/Traverser.java     |   5 +-
 .../metadata/template/ClusterTemplateManager.java  |   2 +-
 .../iotdb/db/metadata/template/Template.java       | 352 ++------------------
 .../metadata/template/TemplateMNodeGenerator.java  |  51 +++
 .../iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java  |  12 +-
 .../iotdb/db/mpp/plan/parser/ASTVisitor.java       |   7 +-
 .../db/mpp/plan/parser/StatementGenerator.java     |   2 +-
 .../template/CreateSchemaTemplateStatement.java    | 121 ++-----
 .../schemaRegion/SchemaRegionManagementTest.java   |   8 +-
 .../schemaRegion/SchemaRegionTemplateTest.java     |  56 +---
 18 files changed, 181 insertions(+), 897 deletions(-)

diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
index dce99b4275..f9dc26d726 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/consensus/request/ConfigPhysicalPlanSerDeTest.java
@@ -854,21 +854,11 @@ public class ConfigPhysicalPlanSerDeTest {
   }
 
   private Template newSchemaTemplate(String name) throws IllegalPathException {
-    List<List<String>> measurements =
-        Arrays.asList(
-            Collections.singletonList(name + "_" + "temperature"),
-            Collections.singletonList(name + "_" + "status"));
-    List<List<TSDataType>> dataTypes =
-        Arrays.asList(
-            Collections.singletonList(TSDataType.FLOAT),
-            Collections.singletonList(TSDataType.BOOLEAN));
-    List<List<TSEncoding>> encodings =
-        Arrays.asList(
-            Collections.singletonList(TSEncoding.RLE), Collections.singletonList(TSEncoding.PLAIN));
-    List<List<CompressionType>> compressors =
-        Arrays.asList(
-            Collections.singletonList(CompressionType.SNAPPY),
-            Collections.singletonList(CompressionType.SNAPPY));
+    List<String> measurements = Arrays.asList(name + "_" + "temperature", name + "_" + "status");
+    List<TSDataType> dataTypes = Arrays.asList(TSDataType.FLOAT, TSDataType.BOOLEAN);
+    List<TSEncoding> encodings = Arrays.asList(TSEncoding.RLE, TSEncoding.PLAIN);
+    List<CompressionType> compressors =
+        Arrays.asList(CompressionType.SNAPPY, CompressionType.SNAPPY);
     return new Template(name, measurements, dataTypes, encodings, compressors);
   }
 
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfoTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfoTest.java
index bbd1673399..1d6e6c607e 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfoTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfoTest.java
@@ -43,7 +43,6 @@ import org.junit.Test;
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -144,21 +143,11 @@ public class ClusterSchemaInfoTest {
   }
 
   private Template newSchemaTemplate(String name) throws IllegalPathException {
-    List<List<String>> measurements =
-        Arrays.asList(
-            Collections.singletonList(name + "_" + "temperature"),
-            Collections.singletonList(name + "_" + "status"));
-    List<List<TSDataType>> dataTypes =
-        Arrays.asList(
-            Collections.singletonList(TSDataType.FLOAT),
-            Collections.singletonList(TSDataType.BOOLEAN));
-    List<List<TSEncoding>> encodings =
-        Arrays.asList(
-            Collections.singletonList(TSEncoding.RLE), Collections.singletonList(TSEncoding.PLAIN));
-    List<List<CompressionType>> compressors =
-        Arrays.asList(
-            Collections.singletonList(CompressionType.SNAPPY),
-            Collections.singletonList(CompressionType.SNAPPY));
+    List<String> measurements = Arrays.asList(name + "_" + "temperature", name + "_" + "status");
+    List<TSDataType> dataTypes = Arrays.asList(TSDataType.FLOAT, TSDataType.BOOLEAN);
+    List<TSEncoding> encodings = Arrays.asList(TSEncoding.RLE, TSEncoding.PLAIN);
+    List<CompressionType> compressors =
+        Arrays.asList(CompressionType.SNAPPY, CompressionType.SNAPPY);
     return new Template(name, measurements, dataTypes, encodings, compressors);
   }
 }
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/persistence/TemplateTableTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/persistence/TemplateTableTest.java
index 6609a51f32..7da7b6cc6c 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/persistence/TemplateTableTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/persistence/TemplateTableTest.java
@@ -37,7 +37,6 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 
 import static org.apache.iotdb.db.constant.TestConstant.BASE_OUTPUT_PATH;
@@ -91,33 +90,20 @@ public class TemplateTableTest {
   }
 
   private Template newSchemaTemplate(String name) throws IllegalPathException {
-    List<List<String>> measurements =
-        Arrays.asList(
-            Collections.singletonList(name + "_" + "temperature"),
-            Collections.singletonList(name + "_" + "status"));
-    List<List<TSDataType>> dataTypes =
-        Arrays.asList(
-            Collections.singletonList(TSDataType.FLOAT),
-            Collections.singletonList(TSDataType.BOOLEAN));
-    List<List<TSEncoding>> encodings =
-        Arrays.asList(
-            Collections.singletonList(TSEncoding.RLE), Collections.singletonList(TSEncoding.PLAIN));
-    List<List<CompressionType>> compressors =
-        Arrays.asList(
-            Collections.singletonList(CompressionType.SNAPPY),
-            Collections.singletonList(CompressionType.SNAPPY));
+    List<String> measurements = Arrays.asList(name + "_" + "temperature", name + "_" + "status");
+    List<TSDataType> dataTypes = Arrays.asList(TSDataType.FLOAT, TSDataType.BOOLEAN);
+    List<TSEncoding> encodings = Arrays.asList(TSEncoding.RLE, TSEncoding.PLAIN);
+    List<CompressionType> compressors =
+        Arrays.asList(CompressionType.SNAPPY, CompressionType.SNAPPY);
     return new Template(name, measurements, dataTypes, encodings, compressors);
   }
 
   private Template newAlignedSchemaTemplate(String name) throws IllegalPathException {
-    List<List<String>> measurements =
-        Collections.singletonList(Arrays.asList(name + "_" + "lat", name + "_" + "lon"));
-    List<List<TSDataType>> dataTypes =
-        Collections.singletonList(Arrays.asList(TSDataType.FLOAT, TSDataType.FLOAT));
-    List<List<TSEncoding>> encodings =
-        Collections.singletonList(Arrays.asList(TSEncoding.GORILLA, TSEncoding.GORILLA));
-    List<List<CompressionType>> compressors =
-        Collections.singletonList(Arrays.asList(CompressionType.SNAPPY, CompressionType.SNAPPY));
-    return new Template(name, measurements, dataTypes, encodings, compressors);
+    List<String> measurements = Arrays.asList(name + "_" + "lat", name + "_" + "lon");
+    List<TSDataType> dataTypes = Arrays.asList(TSDataType.FLOAT, TSDataType.FLOAT);
+    List<TSEncoding> encodings = Arrays.asList(TSEncoding.GORILLA, TSEncoding.GORILLA);
+    List<CompressionType> compressors =
+        Arrays.asList(CompressionType.SNAPPY, CompressionType.SNAPPY);
+    return new Template(name, measurements, dataTypes, encodings, compressors, true);
   }
 }
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/DeactivateTemplateProcedureTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/DeactivateTemplateProcedureTest.java
index cd6205034c..3646578ea7 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/DeactivateTemplateProcedureTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/DeactivateTemplateProcedureTest.java
@@ -49,7 +49,7 @@ public class DeactivateTemplateProcedureTest {
     Template t1 = new Template();
     t1.setId(0);
     t1.setName("t1");
-    t1.addUnalignedMeasurements(
+    t1.addMeasurements(
         new String[] {"s1", "s2"},
         new TSDataType[] {TSDataType.INT32, TSDataType.FLOAT},
         new TSEncoding[] {TSEncoding.PLAIN, TSEncoding.BITMAP},
@@ -58,7 +58,7 @@ public class DeactivateTemplateProcedureTest {
     Template t2 = new Template();
     t2.setId(0);
     t2.setName("t2");
-    t2.addUnalignedMeasurements(
+    t2.addMeasurements(
         new String[] {"s3", "s4"},
         new TSDataType[] {TSDataType.FLOAT, TSDataType.INT32},
         new TSEncoding[] {TSEncoding.BITMAP, TSEncoding.PLAIN},
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/UnsetTemplateProcedureTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/UnsetTemplateProcedureTest.java
index d36d3e281f..b6c05a25f0 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/UnsetTemplateProcedureTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/UnsetTemplateProcedureTest.java
@@ -44,7 +44,7 @@ public class UnsetTemplateProcedureTest {
     Template template = new Template();
     template.setId(0);
     template.setName("t1");
-    template.addUnalignedMeasurements(
+    template.addMeasurements(
         new String[] {"s1", "s2"},
         new TSDataType[] {TSDataType.INT32, TSDataType.FLOAT},
         new TSEncoding[] {TSEncoding.PLAIN, TSEncoding.BITMAP},
diff --git a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBSchemaTemplateIT.java b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBSchemaTemplateIT.java
index 876e329198..5e194a9a21 100644
--- a/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBSchemaTemplateIT.java
+++ b/integration-test/src/test/java/org/apache/iotdb/db/it/schema/IoTDBSchemaTemplateIT.java
@@ -81,6 +81,7 @@ public class IoTDBSchemaTemplateIT extends AbstractSchemaIT {
       // set schema template
       statement.execute("SET SCHEMA TEMPLATE t1 TO root.sg1.d1");
       statement.execute("SET SCHEMA TEMPLATE t2 TO root.sg1.d2");
+      statement.execute("SET SCHEMA TEMPLATE t3 TO root.sg1.d3");
 
       // test drop template which has been set
       try {
@@ -100,6 +101,7 @@ public class IoTDBSchemaTemplateIT extends AbstractSchemaIT {
       // create timeseries of schema template
       statement.execute("CREATE TIMESERIES OF SCHEMA TEMPLATE ON root.sg1.d1");
       statement.execute("CREATE TIMESERIES OF SCHEMA TEMPLATE ON root.sg1.d2");
+      statement.execute("CREATE TIMESERIES OF SCHEMA TEMPLATE ON root.sg1.d3");
 
       Set<String> expectedResult =
           new HashSet<>(
@@ -107,7 +109,8 @@ public class IoTDBSchemaTemplateIT extends AbstractSchemaIT {
                   "root.sg1.d1.s1,INT64,RLE,SNAPPY",
                   "root.sg1.d1.s2,DOUBLE,GORILLA,SNAPPY",
                   "root.sg1.d2.s1,INT64,RLE,SNAPPY",
-                  "root.sg1.d2.s2,DOUBLE,GORILLA,SNAPPY"));
+                  "root.sg1.d2.s2,DOUBLE,GORILLA,SNAPPY",
+                  "root.sg1.d3.s1,INT64,RLE,SNAPPY"));
 
       try (ResultSet resultSet = statement.executeQuery("SHOW TIMESERIES root.sg1.**"); ) {
         while (resultSet.next()) {
@@ -127,10 +130,11 @@ public class IoTDBSchemaTemplateIT extends AbstractSchemaIT {
 
       try (ResultSet resultSet = statement.executeQuery("COUNT TIMESERIES root.sg1.**")) {
         resultSet.next();
-        Assert.assertEquals(4, resultSet.getLong(1));
+        Assert.assertEquals(5, resultSet.getLong(1));
       }
 
-      expectedResult = new HashSet<>(Arrays.asList("root.sg1.d1,false", "root.sg1.d2,true"));
+      expectedResult =
+          new HashSet<>(Arrays.asList("root.sg1.d1,false", "root.sg1.d2,true", "root.sg1.d3,true"));
 
       try (ResultSet resultSet = statement.executeQuery("SHOW DEVICES")) {
         while (resultSet.next()) {
@@ -239,7 +243,7 @@ public class IoTDBSchemaTemplateIT extends AbstractSchemaIT {
   @Test
   public void testDropAndShowSchemaTemplates() throws SQLException {
     // show schema templates
-    String[] expectedResult = new String[] {"t1", "t2"};
+    String[] expectedResult = new String[] {"t1", "t2", "t3"};
     Set<String> expectedResultSet = new HashSet<>(Arrays.asList(expectedResult));
     try (Connection connection = EnvFactory.getEnv().getConnection();
         Statement statement = connection.createStatement()) {
@@ -254,7 +258,7 @@ public class IoTDBSchemaTemplateIT extends AbstractSchemaIT {
 
       // drop schema template
       statement.execute("DROP SCHEMA TEMPLATE t2");
-      expectedResult = new String[] {"t1"};
+      expectedResult = new String[] {"t1", "t3"};
       expectedResultSet = new HashSet<>(Arrays.asList(expectedResult));
       try (ResultSet resultSet = statement.executeQuery("SHOW SCHEMA TEMPLATES")) {
         while (resultSet.next()) {
@@ -398,6 +402,7 @@ public class IoTDBSchemaTemplateIT extends AbstractSchemaIT {
       // create schema template
       statement.execute("CREATE SCHEMA TEMPLATE t1 (s1 INT64, s2 DOUBLE)");
       statement.execute("CREATE SCHEMA TEMPLATE t2 aligned (s1 INT64, s2 DOUBLE)");
+      statement.execute("CREATE SCHEMA TEMPLATE t3 aligned (s1 INT64)");
     }
   }
 
@@ -463,11 +468,11 @@ public class IoTDBSchemaTemplateIT extends AbstractSchemaIT {
   public void testSchemaQueryAndFetchWithUnrelatedTemplate() throws SQLException {
     try (Connection connection = EnvFactory.getEnv().getConnection();
         Statement statement = connection.createStatement()) {
-      statement.execute("CREATE SCHEMA TEMPLATE t3 (s3 INT64, s4 DOUBLE)");
+      statement.execute("CREATE SCHEMA TEMPLATE t4 (s3 INT64, s4 DOUBLE)");
 
       // set schema template
       statement.execute("SET SCHEMA TEMPLATE t1 TO root.sg1.d1");
-      statement.execute("SET SCHEMA TEMPLATE t3 TO root.sg1.d2");
+      statement.execute("SET SCHEMA TEMPLATE t4 TO root.sg1.d2");
 
       // set using schema template
       statement.execute("INSERT INTO root.sg1.d1(time,s1) VALUES (1,1)");
diff --git a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBSchemaTemplateIT.java b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBSchemaTemplateIT.java
deleted file mode 100644
index 88806ab7bb..0000000000
--- a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBSchemaTemplateIT.java
+++ /dev/null
@@ -1,357 +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.integration;
-
-import org.apache.iotdb.db.mpp.common.header.ColumnHeaderConstant;
-import org.apache.iotdb.db.utils.EnvironmentUtils;
-import org.apache.iotdb.itbase.category.LocalStandaloneTest;
-import org.apache.iotdb.jdbc.Config;
-import org.apache.iotdb.jdbc.IoTDBSQLException;
-import org.apache.iotdb.rpc.TSStatusCode;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Notice that, all test begins with "IoTDB" is integration test. All test which will start the
- * IoTDB server should be defined as integration test.
- */
-@Category({LocalStandaloneTest.class})
-public class IoTDBSchemaTemplateIT {
-
-  private Statement statement;
-  private Connection connection;
-
-  @Before
-  public void setUp() throws Exception {
-    EnvironmentUtils.envSetUp();
-
-    Class.forName(Config.JDBC_DRIVER_NAME);
-    connection = DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
-    statement = connection.createStatement();
-
-    prepareTemplate();
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    statement.close();
-    connection.close();
-    EnvironmentUtils.cleanEnv();
-  }
-
-  @Test
-  public void testCreateTemplateAndCreateTimeseries() throws SQLException {
-    // test create schema template repeatedly
-    try {
-      statement.execute(
-          "CREATE SCHEMA TEMPLATE t1 (s1 INT64 encoding=RLE compressor=SNAPPY, s2 INT32)");
-    } catch (IoTDBSQLException e) {
-      Assert.assertEquals(
-          TSStatusCode.METADATA_ERROR.getStatusCode() + ": Duplicated template name: t1",
-          e.getMessage());
-    }
-
-    // set schema template
-    statement.execute("SET SCHEMA TEMPLATE t1 TO root.sg1.d1");
-    statement.execute("SET SCHEMA TEMPLATE t2 TO root.sg1.d2");
-
-    // test drop template which has been set
-    try {
-      statement.execute("DROP SCHEMA TEMPLATE t1");
-    } catch (IoTDBSQLException e) {
-      Assert.assertEquals(
-          TSStatusCode.METADATA_ERROR.getStatusCode()
-              + ": Template [t1] has been set on MTree, cannot be dropped now.",
-          e.getMessage());
-    }
-
-    statement.execute("SHOW TIMESERIES root.sg1.**");
-    try (ResultSet resultSet = statement.getResultSet()) {
-      Assert.assertFalse(resultSet.next());
-    }
-
-    // create timeseries of schema template
-    statement.execute("CREATE TIMESERIES OF SCHEMA TEMPLATE ON root.sg1.d1");
-    statement.execute("CREATE TIMESERIES OF SCHEMA TEMPLATE ON root.sg1.d2");
-
-    boolean hasResult = statement.execute("SHOW TIMESERIES root.sg1.**");
-    Assert.assertTrue(hasResult);
-
-    Set<String> expectedResult =
-        new HashSet<>(
-            Arrays.asList(
-                "root.sg1.d1.s1,INT64,RLE,SNAPPY",
-                "root.sg1.d1.s2,DOUBLE,GORILLA,SNAPPY",
-                "root.sg1.d2.s1,INT64,RLE,SNAPPY",
-                "root.sg1.d2.s2,DOUBLE,GORILLA,SNAPPY"));
-
-    try (ResultSet resultSet = statement.getResultSet()) {
-      while (resultSet.next()) {
-        String actualResult =
-            resultSet.getString(ColumnHeaderConstant.TIMESERIES)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.DATATYPE)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.ENCODING)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.ENCODING);
-        Assert.assertTrue(expectedResult.contains(actualResult));
-        expectedResult.remove(actualResult);
-      }
-    }
-    Assert.assertTrue(expectedResult.isEmpty());
-
-    hasResult = statement.execute("SHOW DEVICES");
-    Assert.assertTrue(hasResult);
-
-    expectedResult = new HashSet<>(Arrays.asList("root.sg1.d1,false", "root.sg1.d2,true"));
-
-    try (ResultSet resultSet = statement.getResultSet()) {
-      while (resultSet.next()) {
-        String actualResult =
-            resultSet.getString(ColumnHeaderConstant.DEVICE)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.IS_ALIGNED);
-        Assert.assertTrue(expectedResult.contains(actualResult));
-        expectedResult.remove(actualResult);
-      }
-    }
-    Assert.assertTrue(expectedResult.isEmpty());
-
-    try {
-      statement.execute("UNSET SCHEMA TEMPLATE t1 FROM root.sg1.d1");
-    } catch (IoTDBSQLException e) {
-      Assert.assertEquals(
-          TSStatusCode.TEMPLATE_IS_IN_USE.getStatusCode() + ": Template is in use on root.sg1.d1",
-          e.getMessage());
-    }
-  }
-
-  @Test
-  public void testCreateAndSetSchemaTemplate() throws SQLException {
-    // test create schema template repeatedly
-    try {
-      statement.execute(
-          "CREATE SCHEMA TEMPLATE t1 (s1 INT64 encoding=RLE compressor=SNAPPY, s2 INT32)");
-    } catch (IoTDBSQLException e) {
-      Assert.assertEquals(
-          TSStatusCode.METADATA_ERROR.getStatusCode() + ": Duplicated template name: t1",
-          e.getMessage());
-    }
-
-    // set schema template
-    statement.execute("SET SCHEMA TEMPLATE t1 TO root.sg1.d1");
-    statement.execute("SET SCHEMA TEMPLATE t2 TO root.sg1.d2");
-
-    statement.execute("SHOW TIMESERIES root.sg1.**");
-    try (ResultSet resultSet = statement.getResultSet()) {
-      Assert.assertFalse(resultSet.next());
-    }
-
-    // set using schema template
-    statement.execute("INSERT INTO root.sg1.d1(time,s1) VALUES (1,1)");
-    statement.execute("INSERT INTO root.sg1.d2(time,s1) ALIGNED VALUES (1,1)");
-
-    boolean hasResult = statement.execute("SHOW TIMESERIES root.sg1.**");
-    Assert.assertTrue(hasResult);
-
-    Set<String> expectedResult =
-        new HashSet<>(
-            Arrays.asList(
-                "root.sg1.d1.s1,INT64,RLE,SNAPPY",
-                "root.sg1.d1.s2,DOUBLE,GORILLA,SNAPPY",
-                "root.sg1.d2.s1,INT64,RLE,SNAPPY",
-                "root.sg1.d2.s2,DOUBLE,GORILLA,SNAPPY"));
-
-    try (ResultSet resultSet = statement.getResultSet()) {
-      while (resultSet.next()) {
-        String actualResult =
-            resultSet.getString(ColumnHeaderConstant.TIMESERIES)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.DATATYPE)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.ENCODING)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.COMPRESSION);
-        Assert.assertTrue(expectedResult.contains(actualResult));
-        expectedResult.remove(actualResult);
-      }
-    }
-    Assert.assertTrue(expectedResult.isEmpty());
-
-    hasResult = statement.execute("SHOW DEVICES");
-    Assert.assertTrue(hasResult);
-
-    expectedResult = new HashSet<>(Arrays.asList("root.sg1.d1,false", "root.sg1.d2,true"));
-
-    try (ResultSet resultSet = statement.getResultSet()) {
-      while (resultSet.next()) {
-        String actualResult =
-            resultSet.getString(ColumnHeaderConstant.DEVICE)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.IS_ALIGNED);
-        Assert.assertTrue(expectedResult.contains(actualResult));
-        expectedResult.remove(actualResult);
-      }
-    }
-    Assert.assertTrue(expectedResult.isEmpty());
-
-    try {
-      statement.execute("UNSET SCHEMA TEMPLATE t1 FROM root.sg1.d1");
-    } catch (IoTDBSQLException e) {
-      Assert.assertEquals(
-          TSStatusCode.TEMPLATE_IS_IN_USE.getStatusCode() + ": Template is in use on root.sg1.d1",
-          e.getMessage());
-    }
-  }
-
-  @Test
-  public void testDropAndShowSchemaTemplates() throws SQLException {
-    // show schema templates
-    statement.execute("SHOW SCHEMA TEMPLATES");
-    String[] expectedResult = new String[] {"t1", "t2"};
-    Set<String> expectedResultSet = new HashSet<>(Arrays.asList(expectedResult));
-    try (ResultSet resultSet = statement.getResultSet()) {
-      while (resultSet.next()) {
-        Assert.assertTrue(
-            expectedResultSet.contains(resultSet.getString(ColumnHeaderConstant.TEMPLATE_NAME)));
-        expectedResultSet.remove(resultSet.getString(ColumnHeaderConstant.TEMPLATE_NAME));
-      }
-    }
-    Assert.assertEquals(0, expectedResultSet.size());
-
-    // drop schema template
-    statement.execute("DROP SCHEMA TEMPLATE t2");
-    statement.execute("SHOW SCHEMA TEMPLATES");
-    expectedResult = new String[] {"t1"};
-    expectedResultSet = new HashSet<>(Arrays.asList(expectedResult));
-    try (ResultSet resultSet = statement.getResultSet()) {
-      while (resultSet.next()) {
-        Assert.assertTrue(
-            expectedResultSet.contains(resultSet.getString(ColumnHeaderConstant.TEMPLATE_NAME)));
-        expectedResultSet.remove(resultSet.getString(ColumnHeaderConstant.TEMPLATE_NAME));
-      }
-    }
-    Assert.assertEquals(0, expectedResultSet.size());
-  }
-
-  @Test
-  public void testShowNodesInSchemaTemplate() throws SQLException {
-    // set schema template
-    statement.execute("SHOW NODES IN SCHEMA TEMPLATE t1");
-    Set<String> expectedResultSet =
-        new HashSet<>(Arrays.asList("s1,INT64,RLE,SNAPPY", "s2,DOUBLE,GORILLA,SNAPPY"));
-    try (ResultSet resultSet = statement.getResultSet()) {
-      while (resultSet.next()) {
-        String actualResult =
-            resultSet.getString(ColumnHeaderConstant.CHILD_NODES)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.DATATYPE)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.ENCODING)
-                + ","
-                + resultSet.getString(ColumnHeaderConstant.COMPRESSION);
-        Assert.assertTrue(expectedResultSet.contains(actualResult));
-        expectedResultSet.remove(actualResult);
-      }
-    }
-    Assert.assertEquals(0, expectedResultSet.size());
-  }
-
-  @Test
-  public void testShowPathsSetOrUsingSchemaTemplate() throws SQLException {
-    // set schema template
-    statement.execute("SET SCHEMA TEMPLATE t1 TO root.sg1.d1");
-    statement.execute("SET SCHEMA TEMPLATE t1 TO root.sg1.d2");
-    statement.execute("SET SCHEMA TEMPLATE t1 TO root.sg2.d1");
-    statement.execute("SET SCHEMA TEMPLATE t1 TO root.sg2.d2");
-    statement.execute("SET SCHEMA TEMPLATE t2 TO root.sg3.d1");
-    statement.execute("SET SCHEMA TEMPLATE t2 TO root.sg3.d2");
-
-    // activate schema template
-    statement.execute("CREATE TIMESERIES OF SCHEMA TEMPLATE ON root.sg1.d2");
-    statement.execute("CREATE TIMESERIES OF SCHEMA TEMPLATE ON root.sg2.d1");
-
-    // show paths set schema template
-    statement.execute("SHOW PATHS SET SCHEMA TEMPLATE t1");
-    String[] expectedResult =
-        new String[] {"root.sg1.d1", "root.sg2.d2", "root.sg1.d2", "root.sg2.d1"};
-    Set<String> expectedResultSet = new HashSet<>(Arrays.asList(expectedResult));
-    try (ResultSet resultSet = statement.getResultSet()) {
-      while (resultSet.next()) {
-        Assert.assertTrue(
-            expectedResultSet.contains(resultSet.getString(ColumnHeaderConstant.CHILD_PATHS)));
-        expectedResultSet.remove(resultSet.getString(ColumnHeaderConstant.CHILD_PATHS));
-      }
-    }
-    Assert.assertEquals(0, expectedResultSet.size());
-
-    statement.execute("SHOW PATHS SET SCHEMA TEMPLATE t2");
-    expectedResult = new String[] {"root.sg3.d1", "root.sg3.d2"};
-    expectedResultSet = new HashSet<>(Arrays.asList(expectedResult));
-    try (ResultSet resultSet = statement.getResultSet()) {
-      while (resultSet.next()) {
-        Assert.assertTrue(
-            expectedResultSet.contains(resultSet.getString(ColumnHeaderConstant.CHILD_PATHS)));
-        expectedResultSet.remove(resultSet.getString(ColumnHeaderConstant.CHILD_PATHS));
-      }
-    }
-    Assert.assertEquals(0, expectedResultSet.size());
-
-    statement.execute("SHOW PATHS USING SCHEMA TEMPLATE t1");
-    expectedResult = new String[] {"root.sg1.d2", "root.sg2.d1"};
-    expectedResultSet = new HashSet<>(Arrays.asList(expectedResult));
-    try (ResultSet resultSet = statement.getResultSet()) {
-      while (resultSet.next()) {
-        Assert.assertTrue(
-            expectedResultSet.contains(resultSet.getString(ColumnHeaderConstant.CHILD_PATHS)));
-        expectedResultSet.remove(resultSet.getString(ColumnHeaderConstant.CHILD_PATHS));
-      }
-    }
-    Assert.assertEquals(0, expectedResultSet.size());
-
-    statement.execute("SHOW PATHS USING SCHEMA TEMPLATE t2");
-    ResultSet resultSet = statement.getResultSet();
-    Assert.assertFalse(resultSet.next());
-  }
-
-  private void prepareTemplate() throws SQLException {
-    // create database
-    statement.execute("CREATE DATABASE root.sg1");
-    statement.execute("CREATE DATABASE root.sg2");
-    statement.execute("CREATE DATABASE root.sg3");
-
-    // create schema template
-    statement.execute("CREATE SCHEMA TEMPLATE t1 (s1 INT64, s2 DOUBLE)");
-    statement.execute("CREATE SCHEMA TEMPLATE t2 aligned (s1 INT64, s2 DOUBLE)");
-  }
-}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/iterator/AbstractTraverserIterator.java b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/iterator/AbstractTraverserIterator.java
index 821c901de5..026fd03660 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mnode/iterator/AbstractTraverserIterator.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mnode/iterator/AbstractTraverserIterator.java
@@ -23,6 +23,7 @@ import org.apache.iotdb.db.metadata.mnode.IEntityMNode;
 import org.apache.iotdb.db.metadata.mnode.IMNode;
 import org.apache.iotdb.db.metadata.mtree.store.IMTreeStore;
 import org.apache.iotdb.db.metadata.template.Template;
+import org.apache.iotdb.db.metadata.template.TemplateMNodeGenerator;
 
 import java.util.Iterator;
 import java.util.Map;
@@ -49,7 +50,7 @@ public abstract class AbstractTraverserIterator implements IMNodeIterator {
     if (templateMap != null && parent.isUseTemplate()) {
       Template template = getActivatedSchemaTemplate(parent, templateMap);
       if (template != null) {
-        templateChildrenIterator = template.getDirectNodes().iterator();
+        templateChildrenIterator = TemplateMNodeGenerator.getChildren(template);
       }
     }
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/traverser/Traverser.java b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/traverser/Traverser.java
index 4a55d9ef56..485915d988 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/mtree/traverser/Traverser.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/mtree/traverser/Traverser.java
@@ -28,6 +28,7 @@ import org.apache.iotdb.db.metadata.mnode.iterator.MNodeIterator;
 import org.apache.iotdb.db.metadata.mtree.store.IMTreeStore;
 import org.apache.iotdb.db.metadata.mtree.store.ReentrantReadOnlyCachedMTreeStore;
 import org.apache.iotdb.db.metadata.template.Template;
+import org.apache.iotdb.db.metadata.template.TemplateMNodeGenerator;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -123,7 +124,9 @@ public abstract class Traverser<R> extends AbstractTreeVisitor<IMNode, R> {
         // if null, it means the template on this device is not covered in this query, refer to the
         // mpp analyzing stage
         if (template != null) {
-          child = templateMap.get(parent.getSchemaTemplateId()).getDirectNode(childName);
+          child =
+              TemplateMNodeGenerator.getChild(
+                  templateMap.get(parent.getSchemaTemplateId()), childName);
         }
       }
     }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java b/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java
index 1350a07a04..5e85c84374 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/template/ClusterTemplateManager.java
@@ -114,7 +114,7 @@ public class ClusterTemplateManager implements ITemplateManager {
               statement.getDataTypes(),
               statement.getEncodings(),
               statement.getCompressors(),
-              statement.getAlignedDeviceId());
+              statement.isAligned());
       req.setName(template.getName());
       req.setSerializedTemplate(template.serialize());
     } catch (IllegalPathException e) {
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/template/Template.java b/server/src/main/java/org/apache/iotdb/db/metadata/template/Template.java
index a2a2130cce..1d6688c0ea 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/template/Template.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/template/Template.java
@@ -19,14 +19,6 @@
 package org.apache.iotdb.db.metadata.template;
 
 import org.apache.iotdb.commons.exception.IllegalPathException;
-import org.apache.iotdb.commons.path.PartialPath;
-import org.apache.iotdb.commons.utils.PathUtils;
-import org.apache.iotdb.db.metadata.mnode.EntityMNode;
-import org.apache.iotdb.db.metadata.mnode.IEntityMNode;
-import org.apache.iotdb.db.metadata.mnode.IMNode;
-import org.apache.iotdb.db.metadata.mnode.IMeasurementMNode;
-import org.apache.iotdb.db.metadata.mnode.MeasurementMNode;
-import org.apache.iotdb.tsfile.common.constant.TsFileConstant;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
@@ -42,14 +34,9 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Serializable;
 import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 public class Template implements Serializable {
 
@@ -58,83 +45,38 @@ public class Template implements Serializable {
   private boolean isDirectAligned;
   private Map<String, IMeasurementSchema> schemaMap;
 
-  private transient Map<String, IMNode> directNodes;
-
   private transient int rehashCode;
 
   public Template() {
     schemaMap = new HashMap<>();
-    directNodes = new HashMap<>();
   }
 
   public Template(
       String name,
-      List<List<String>> measurements,
-      List<List<TSDataType>> dataTypes,
-      List<List<TSEncoding>> encodings,
-      List<List<CompressionType>> compressors)
+      List<String> measurements,
+      List<TSDataType> dataTypes,
+      List<TSEncoding> encodings,
+      List<CompressionType> compressors)
       throws IllegalPathException {
-    this(name, measurements, dataTypes, encodings, compressors, null);
+    this(name, measurements, dataTypes, encodings, compressors, false);
   }
 
   public Template(
       String name,
-      List<List<String>> measurements,
-      List<List<TSDataType>> dataTypes,
-      List<List<TSEncoding>> encodings,
-      List<List<CompressionType>> compressors,
-      Set<String> alignedDeviceId)
+      List<String> measurements,
+      List<TSDataType> dataTypes,
+      List<TSEncoding> encodings,
+      List<CompressionType> compressors,
+      boolean isAligned)
       throws IllegalPathException {
-    boolean isAlign;
-    schemaMap = new HashMap<>();
+    this.isDirectAligned = isAligned;
+    this.schemaMap = new HashMap<>();
     this.name = name;
-    isDirectAligned = false;
-    directNodes = new HashMap<>();
-    rehashCode = 0;
-
     for (int i = 0; i < measurements.size(); i++) {
-      IMeasurementSchema curSchema;
-      int size = measurements.get(i).size();
-      if (size > 1) {
-        isAlign = true;
-      } else {
-        // If sublist of measurements has only one item,
-        // but it shares prefix with other aligned sublist, it will be aligned too
-        String[] thisMeasurement = PathUtils.splitPathToDetachedNodes(measurements.get(i).get(0));
-        String thisPrefix =
-            joinBySeparator(Arrays.copyOf(thisMeasurement, thisMeasurement.length - 1));
-        isAlign = alignedDeviceId != null && alignedDeviceId.contains(thisPrefix);
-      }
-
-      // vector, aligned measurements
-      if (isAlign) {
-        IMeasurementSchema[] curSchemas;
-        String[] measurementsArray = new String[size];
-        TSDataType[] typeArray = new TSDataType[size];
-        TSEncoding[] encodingArray = new TSEncoding[size];
-        CompressionType[] compressorArray = new CompressionType[size];
-
-        for (int j = 0; j < size; j++) {
-          measurementsArray[j] = measurements.get(i).get(j);
-          typeArray[j] = dataTypes.get(i).get(j);
-          encodingArray[j] = encodings.get(i).get(j);
-          compressorArray[j] = compressors.get(i).get(j);
-        }
-
-        curSchemas = constructSchemas(measurementsArray, typeArray, encodingArray, compressorArray);
-        constructTemplateTree(measurementsArray, curSchemas);
-
-      }
-      // normal measurement
-      else {
-        curSchema =
-            new MeasurementSchema(
-                measurements.get(i).get(0),
-                dataTypes.get(i).get(0),
-                encodings.get(i).get(0),
-                compressors.get(i).get(0));
-        constructTemplateTree(measurements.get(i).get(0), curSchema);
-      }
+      IMeasurementSchema schema =
+          new MeasurementSchema(
+              measurements.get(i), dataTypes.get(i), encodings.get(i), compressors.get(i));
+      schemaMap.put(schema.getMeasurementId(), schema);
     }
   }
 
@@ -171,273 +113,33 @@ public class Template implements Serializable {
   }
 
   // region construct template tree
-  /** Construct aligned measurements, checks prefix equality, path duplication and conflict */
-  private void constructTemplateTree(String[] alignedPaths, IMeasurementSchema[] schemas)
-      throws IllegalPathException {
-    // Only for aligned Paths, with common direct prefix
-    String[] pathNodes;
-    IMNode commonPar;
-    String prefix = null;
-    List<String> measurementNames = new ArrayList<>();
-    IMeasurementMNode leafNode;
-
-    // deduplicate
-    Set<String> pathSet = new HashSet<>(Arrays.asList(alignedPaths));
-    if (pathSet.size() != alignedPaths.length) {
-      throw new IllegalPathException("Duplication in paths.");
-    }
-
-    Set<String> checkSet = new HashSet<>();
-    for (String path : alignedPaths) {
-      // check aligned whether legal, and records measurements name
-      if (getPathNodeInTemplate(path) != null) {
-        throw new IllegalPathException("Path duplicated: " + path);
-      }
-      pathNodes = PathUtils.splitPathToDetachedNodes(path);
-
-      if (pathNodes.length == 1) {
-        prefix = "";
-      } else {
-        prefix = joinBySeparator(Arrays.copyOf(pathNodes, pathNodes.length - 1));
-      }
-
-      if (checkSet.isEmpty()) {
-        checkSet.add(prefix);
-      }
-      if (!checkSet.contains(prefix)) {
-        throw new IllegalPathException(
-            "Aligned measurements get different paths, " + alignedPaths[0]);
-      }
-
-      measurementNames.add(pathNodes[pathNodes.length - 1]);
-    }
-
-    synchronized (this) {
-      if (prefix.equals("")) {
-        isDirectAligned = true;
-      }
-      for (int i = 0; i <= measurementNames.size() - 1; i++) {
-        // find the parent and add nodes to template
-        if ("".equals(prefix)) {
-          leafNode =
-              MeasurementMNode.getMeasurementMNode(null, measurementNames.get(i), schemas[i], null);
-          directNodes.put(leafNode.getName(), leafNode);
-        } else {
-          commonPar = constructEntityPath(alignedPaths[0]);
-          commonPar.getAsEntityMNode().setAligned(true);
-          leafNode =
-              MeasurementMNode.getMeasurementMNode(
-                  commonPar.getAsEntityMNode(), measurementNames.get(i), schemas[i], null);
-          commonPar.addChild(leafNode);
-        }
-        schemaMap.put(getFullPathWithoutTemplateName(leafNode), schemas[i]);
-      }
-    }
-  }
-
-  /** Construct single measurement, only check path conflict and duplication */
-  private IMeasurementMNode constructTemplateTree(String path, IMeasurementSchema schema)
-      throws IllegalPathException {
-    if (getPathNodeInTemplate(path) != null) {
-      throw new IllegalPathException("Path duplicated: " + path);
-    }
-    String[] pathNode = PathUtils.splitPathToDetachedNodes(path);
-    IMNode cur = constructEntityPath(path);
-
-    synchronized (this) {
-      IMeasurementMNode leafNode =
-          MeasurementMNode.getMeasurementMNode(
-              (IEntityMNode) cur, pathNode[pathNode.length - 1], schema, null);
-      if (cur == null) {
-        directNodes.put(leafNode.getName(), leafNode);
-      } else {
-        cur.addChild(leafNode);
-      }
-      schemaMap.put(getFullPathWithoutTemplateName(leafNode), schema);
-      return leafNode;
-    }
-  }
 
   private IMeasurementSchema constructSchema(
       String nodeName, TSDataType dataType, TSEncoding encoding, CompressionType compressor) {
     return new MeasurementSchema(nodeName, dataType, encoding, compressor);
   }
 
-  private IMeasurementSchema[] constructSchemas(
-      String[] nodeNames,
-      TSDataType[] dataTypes,
-      TSEncoding[] encodings,
-      CompressionType[] compressors)
-      throws IllegalPathException {
-    MeasurementSchema[] schemas = new MeasurementSchema[nodeNames.length];
-    for (int i = 0; i < nodeNames.length; i++) {
-      schemas[i] =
-          new MeasurementSchema(
-              new PartialPath(nodeNames[i]).getMeasurement(),
-              dataTypes[i],
-              encodings[i],
-              compressors[i]);
-    }
-    return schemas;
-  }
-  // endregion
-
-  // region query of template
-
-  public IMNode getPathNodeInTemplate(String path) throws IllegalPathException {
-    return getPathNodeInTemplate(PathUtils.splitPathToDetachedNodes(path));
-  }
-
-  private IMNode getPathNodeInTemplate(String[] pathNodes) {
-    if (pathNodes.length == 0) {
-      return null;
-    }
-    IMNode cur = directNodes.getOrDefault(pathNodes[0], null);
-    if (cur == null || cur.isMeasurement()) {
-      return cur;
-    }
-    for (int i = 1; i < pathNodes.length; i++) {
-      if (cur.hasChild(pathNodes[i])) {
-        cur = cur.getChild(pathNodes[i]);
-      } else {
-        return null;
-      }
-    }
-    return cur;
-  }
-
-  public IMNode getDirectNode(String nodeName) {
-    return directNodes.getOrDefault(nodeName, null);
-  }
-
-  public Collection<IMNode> getDirectNodes() {
-    return directNodes.values();
-  }
-
-  // endregion
-
-  // region inner utils
-
-  private String getFullPathWithoutTemplateName(IMNode node) {
-    if (node == null) {
-      return "";
-    }
-    StringBuilder builder = new StringBuilder(node.getName());
-    IMNode cur = node.getParent();
-    while (cur != null) {
-      builder.insert(0, cur.getName() + TsFileConstant.PATH_SEPARATOR);
-      cur = cur.getParent();
-    }
-    return builder.toString();
-  }
-
-  /**
-   * @param path complete path to measurement.
-   * @return null if need to add direct node, will never return a measurement.
-   */
-  private IMNode constructEntityPath(String path) throws IllegalPathException {
-    String[] pathNodes = PathUtils.splitPathToDetachedNodes(path);
-    if (pathNodes.length == 1) {
-      return null;
-    }
-
-    IMNode cur = directNodes.get(pathNodes[0]);
-    if (cur == null) {
-      cur = new EntityMNode(null, pathNodes[0]);
-      directNodes.put(pathNodes[0], cur);
-    }
-
-    if (cur.isMeasurement()) {
-      throw new IllegalPathException(path, "there is measurement in path.");
-    }
-
-    for (int i = 1; i <= pathNodes.length - 2; i++) {
-      if (!cur.hasChild(pathNodes[i])) {
-        cur.addChild(pathNodes[i], new EntityMNode(cur, pathNodes[i]));
-      }
-      cur = cur.getChild(pathNodes[i]);
-
-      if (cur.isMeasurement()) {
-        throw new IllegalPathException(path, "there is measurement in path.");
-      }
-    }
-    return cur;
-  }
-
-  private static String joinBySeparator(String[] pathNodes) {
-    if ((pathNodes == null) || (pathNodes.length == 0)) {
-      return "";
-    }
-    StringBuilder builder = new StringBuilder(pathNodes[0]);
-    for (int i = 1; i <= pathNodes.length - 1; i++) {
-      builder.append(TsFileConstant.PATH_SEPARATOR);
-      builder.append(pathNodes[i]);
-    }
-    return builder.toString();
-  }
   // endregion
 
   // region append of template
 
-  public void addAlignedMeasurements(
-      String[] measurements,
-      TSDataType[] dataTypes,
-      TSEncoding[] encodings,
-      CompressionType[] compressors)
-      throws IllegalPathException {
-    IMeasurementSchema[] schema;
-    String prefix;
-    String[] pathNode;
-    String[] leafNodes = new String[measurements.length];
-
-    // If prefix exists and not aligned, it will throw exception
-    // Prefix equality will be checked in constructTemplateTree
-    pathNode = PathUtils.splitPathToDetachedNodes(measurements[0]);
-    prefix = joinBySeparator(Arrays.copyOf(pathNode, pathNode.length - 1));
-    IMNode targetNode = getPathNodeInTemplate(prefix);
-    if ((targetNode != null && !targetNode.getAsEntityMNode().isAligned())
-        || (prefix.equals("") && !this.isDirectAligned())) {
-      throw new IllegalPathException(prefix, "path already exists but not aligned");
-    }
-
-    for (int i = 0; i <= measurements.length - 1; i++) {
-      pathNode = PathUtils.splitPathToDetachedNodes(measurements[i]);
-      leafNodes[i] = pathNode[pathNode.length - 1];
-    }
-    schema = constructSchemas(leafNodes, dataTypes, encodings, compressors);
-    constructTemplateTree(measurements, schema);
-  }
-
-  public void addUnalignedMeasurements(
+  public void addMeasurements(
       String[] measurements,
       TSDataType[] dataTypes,
       TSEncoding[] encodings,
       CompressionType[] compressors)
       throws IllegalPathException {
-    String prefix;
-    String[] pathNode;
-
-    // deduplicate
-    Set<String> pathSet = new HashSet<>(Arrays.asList(measurements));
-    if (pathSet.size() != measurements.length) {
-      throw new IllegalPathException("Duplication in paths.");
-    }
-
-    for (int i = 0; i <= measurements.length - 1; i++) {
-      pathNode = PathUtils.splitPathToDetachedNodes(measurements[i]);
-
-      // If prefix exists and aligned, it will throw exception
-      prefix = joinBySeparator(Arrays.copyOf(pathNode, pathNode.length - 1));
-      IMNode parNode = getPathNodeInTemplate(prefix);
-      if ((parNode != null && parNode.getAsEntityMNode().isAligned())
-          || (prefix.equals("") && this.isDirectAligned())) {
-        throw new IllegalPathException(measurements[i], "path already exists and aligned");
+    // check exists
+    for (String measurement : measurements) {
+      if (schemaMap.containsKey(measurement)) {
+        throw new IllegalPathException(measurement, "path already exists");
       }
-
+    }
+    // construct
+    for (int i = 0; i < measurements.length; i++) {
       IMeasurementSchema schema =
-          constructSchema(
-              pathNode[pathNode.length - 1], dataTypes[i], encodings[i], compressors[i]);
-      constructTemplateTree(measurements[i], schema);
+          constructSchema(measurements[i], dataTypes[i], encodings[i], compressors[i]);
+      schemaMap.put(measurements[i], schema);
     }
   }
 
@@ -481,7 +183,6 @@ public class Template implements Serializable {
     isDirectAligned = ReadWriteIOUtils.readBool(buffer);
     int schemaSize = ReadWriteIOUtils.readInt(buffer);
     schemaMap = new HashMap<>(schemaSize);
-    directNodes = new HashMap<>(schemaSize);
     for (int i = 0; i < schemaSize; i++) {
       String schemaName = ReadWriteIOUtils.readString(buffer);
       byte flag = ReadWriteIOUtils.readByte(buffer);
@@ -492,7 +193,6 @@ public class Template implements Serializable {
         measurementSchema = VectorMeasurementSchema.partialDeserializeFrom(buffer);
       }
       schemaMap.put(schemaName, measurementSchema);
-      directNodes.put(schemaName, new MeasurementMNode(null, schemaName, measurementSchema, null));
     }
   }
 
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/template/TemplateMNodeGenerator.java b/server/src/main/java/org/apache/iotdb/db/metadata/template/TemplateMNodeGenerator.java
new file mode 100644
index 0000000000..b22ed3ab3f
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/template/TemplateMNodeGenerator.java
@@ -0,0 +1,51 @@
+/*
+ * 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.template;
+
+import org.apache.iotdb.db.metadata.mnode.IMNode;
+import org.apache.iotdb.db.metadata.mnode.MeasurementMNode;
+import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
+
+import java.util.Iterator;
+
+// TODO: it will be generic later
+public class TemplateMNodeGenerator {
+  public static IMNode getChild(Template template, String name) {
+    IMeasurementSchema schema = template.getSchema(name);
+    return schema == null ? null : new MeasurementMNode(null, name, template.getSchema(name), null);
+  }
+
+  public static Iterator<IMNode> getChildren(Template template) {
+    return new Iterator<IMNode>() {
+      private final Iterator<IMeasurementSchema> schemas =
+          template.getSchemaMap().values().iterator();
+
+      @Override
+      public boolean hasNext() {
+        return schemas.hasNext();
+      }
+
+      @Override
+      public IMNode next() {
+        IMeasurementSchema schema = schemas.next();
+        return new MeasurementMNode(null, schema.getMeasurementId(), schema, null);
+      }
+    };
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
index 25953f8460..23859061e1 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
@@ -2615,13 +2615,11 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
       CreateSchemaTemplateStatement createTemplateStatement, MPPQueryContext context) {
 
     context.setQueryType(QueryType.WRITE);
-    List<List<String>> measurementsList = createTemplateStatement.getMeasurements();
-    for (List<String> measurements : measurementsList) {
-      Set<String> measurementsSet = new HashSet<>(measurements);
-      if (measurementsSet.size() < measurements.size()) {
-        throw new SemanticException(
-            "Measurement under an aligned device is not allowed to have the same measurement name");
-      }
+    List<String> measurements = createTemplateStatement.getMeasurements();
+    Set<String> measurementsSet = new HashSet<>(measurements);
+    if (measurementsSet.size() < measurements.size()) {
+      throw new SemanticException(
+          "Measurement under template is not allowed to have the same measurement name");
     }
     Analysis analysis = new Analysis();
     analysis.setStatement(createTemplateStatement);
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
index b31ccbd50f..b54854825f 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/ASTVisitor.java
@@ -2839,7 +2839,12 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
     }
 
     return new CreateSchemaTemplateStatement(
-        name, measurementsList, dataTypesList, encodingsList, compressorsList);
+        name,
+        measurementsList,
+        dataTypesList,
+        encodingsList,
+        compressorsList,
+        ctx.ALIGNED() != null);
   }
 
   void parseAttributeClause(
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/StatementGenerator.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/StatementGenerator.java
index ef0e19cdca..97fafec498 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/StatementGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/StatementGenerator.java
@@ -643,7 +643,7 @@ public class StatementGenerator {
     }
     CreateSchemaTemplateStatement statement =
         new CreateSchemaTemplateStatement(
-            req.getName(), measurements, dataTypes, encodings, compressors, alignedPrefix.keySet());
+            req.getName(), measurements, dataTypes, encodings, compressors, isAlign);
     PerformanceOverviewMetricsManager.getInstance().recordParseCost(System.nanoTime() - startTime);
     return statement;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/CreateSchemaTemplateStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/CreateSchemaTemplateStatement.java
index f98d9b4983..a5c2ed3ef3 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/CreateSchemaTemplateStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/template/CreateSchemaTemplateStatement.java
@@ -29,20 +29,17 @@ 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 java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
+import java.util.stream.Collectors;
 
 public class CreateSchemaTemplateStatement extends Statement implements IConfigStatement {
 
   String name;
-  Set<String> alignedDeviceId;
-  String[][] measurements;
-  TSDataType[][] dataTypes;
-  TSEncoding[][] encodings;
-  CompressionType[][] compressors;
+  List<String> measurements;
+  List<TSDataType> dataTypes;
+  List<TSEncoding> encodings;
+  List<CompressionType> compressors;
+  boolean isAligned;
 
   // constant to help resolve serialized sequence
   private static final int NEW_PLAN = -1;
@@ -52,72 +49,28 @@ public class CreateSchemaTemplateStatement extends Statement implements IConfigS
     statementType = StatementType.CREATE_TEMPLATE;
   }
 
-  public CreateSchemaTemplateStatement(
-      String name,
-      List<List<String>> measurements,
-      List<List<TSDataType>> dataTypes,
-      List<List<TSEncoding>> encodings,
-      List<List<CompressionType>> compressors) {
-    this();
-    this.name = name;
-    this.measurements = new String[measurements.size()][];
-    for (int i = 0; i < measurements.size(); i++) {
-      this.measurements[i] = new String[measurements.get(i).size()];
-      for (int j = 0; j < measurements.get(i).size(); j++) {
-        this.measurements[i][j] = measurements.get(i).get(j);
-      }
-    }
-
-    this.dataTypes = new TSDataType[dataTypes.size()][];
-    for (int i = 0; i < dataTypes.size(); i++) {
-      this.dataTypes[i] = new TSDataType[dataTypes.get(i).size()];
-      for (int j = 0; j < dataTypes.get(i).size(); j++) {
-        this.dataTypes[i][j] = dataTypes.get(i).get(j);
-      }
-    }
-
-    this.encodings = new TSEncoding[dataTypes.size()][];
-    for (int i = 0; i < encodings.size(); i++) {
-      this.encodings[i] = new TSEncoding[dataTypes.get(i).size()];
-      for (int j = 0; j < encodings.get(i).size(); j++) {
-        this.encodings[i][j] = encodings.get(i).get(j);
-      }
-    }
-
-    this.compressors = new CompressionType[dataTypes.size()][];
-    for (int i = 0; i < compressors.size(); i++) {
-      this.compressors[i] = new CompressionType[compressors.get(i).size()];
-      for (int j = 0; j < compressors.get(i).size(); j++) {
-        this.compressors[i][j] = compressors.get(i).get(j);
-      }
-    }
-    this.alignedDeviceId = new HashSet<>();
-  }
-
   public CreateSchemaTemplateStatement(
       String name,
       List<List<String>> measurements,
       List<List<TSDataType>> dataTypes,
       List<List<TSEncoding>> encodings,
       List<List<CompressionType>> compressors,
-      Set<String> alignedDeviceId) {
+      boolean aligned) {
     // Only accessed by deserialization, which may cause ambiguity with align designation
-    this(name, measurements, dataTypes, encodings, compressors);
-    this.alignedDeviceId = alignedDeviceId;
-  }
-
-  public CreateSchemaTemplateStatement(
-      String name,
-      String[][] measurements,
-      TSDataType[][] dataTypes,
-      TSEncoding[][] encodings,
-      CompressionType[][] compressors) {
     this();
     this.name = name;
-    this.measurements = measurements;
-    this.dataTypes = dataTypes;
-    this.encodings = encodings;
-    this.compressors = compressors;
+    this.isAligned = aligned;
+    if (aligned) {
+      this.measurements = measurements.get(0);
+      this.dataTypes = dataTypes.get(0);
+      this.encodings = encodings.get(0);
+      this.compressors = compressors.get(0);
+    } else {
+      this.measurements = measurements.stream().map(i -> i.get(0)).collect(Collectors.toList());
+      this.dataTypes = dataTypes.stream().map(i -> i.get(0)).collect(Collectors.toList());
+      this.encodings = encodings.stream().map(i -> i.get(0)).collect(Collectors.toList());
+      this.compressors = compressors.stream().map(i -> i.get(0)).collect(Collectors.toList());
+    }
   }
 
   @Override
@@ -133,40 +86,24 @@ public class CreateSchemaTemplateStatement extends Statement implements IConfigS
     this.name = name;
   }
 
-  public Set<String> getAlignedDeviceId() {
-    return alignedDeviceId;
+  public List<String> getMeasurements() {
+    return measurements;
   }
 
-  public List<List<String>> getMeasurements() {
-    List<List<String>> ret = new ArrayList<>();
-    for (String[] measurement : measurements) {
-      ret.add(Arrays.asList(measurement));
-    }
-    return ret;
+  public List<TSDataType> getDataTypes() {
+    return dataTypes;
   }
 
-  public List<List<TSDataType>> getDataTypes() {
-    List<List<TSDataType>> ret = new ArrayList<>();
-    for (TSDataType[] alignedDataTypes : dataTypes) {
-      ret.add(Arrays.asList(alignedDataTypes));
-    }
-    return ret;
+  public List<TSEncoding> getEncodings() {
+    return encodings;
   }
 
-  public List<List<TSEncoding>> getEncodings() {
-    List<List<TSEncoding>> ret = new ArrayList<>();
-    for (TSEncoding[] alignedEncodings : encodings) {
-      ret.add(Arrays.asList(alignedEncodings));
-    }
-    return ret;
+  public List<CompressionType> getCompressors() {
+    return compressors;
   }
 
-  public List<List<CompressionType>> getCompressors() {
-    List<List<CompressionType>> ret = new ArrayList<>();
-    for (CompressionType[] alignedCompressor : compressors) {
-      ret.add(Arrays.asList(alignedCompressor));
-    }
-    return ret;
+  public boolean isAligned() {
+    return isAligned;
   }
 
   @Override
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionManagementTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionManagementTest.java
index c6540041f2..c26746d859 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionManagementTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionManagementTest.java
@@ -147,10 +147,10 @@ public class SchemaRegionManagementTest extends AbstractSchemaRegionTest {
     Template template =
         new Template(
             "t1",
-            Collections.singletonList(Collections.singletonList("s1")),
-            Collections.singletonList(Collections.singletonList(TSDataType.INT32)),
-            Collections.singletonList(Collections.singletonList(TSEncoding.PLAIN)),
-            Collections.singletonList(Collections.singletonList(CompressionType.GZIP)));
+            Collections.singletonList("s1"),
+            Collections.singletonList(TSDataType.INT32),
+            Collections.singletonList(TSEncoding.PLAIN),
+            Collections.singletonList(CompressionType.GZIP));
     template.setId(1);
     return template;
   }
diff --git a/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTemplateTest.java b/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTemplateTest.java
index 2afaad5069..206eabc08f 100644
--- a/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTemplateTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metadata/schemaRegion/SchemaRegionTemplateTest.java
@@ -71,16 +71,10 @@ public class SchemaRegionTemplateTest extends AbstractSchemaRegionTest {
     Template template =
         new Template(
             "t1",
-            Arrays.asList(Collections.singletonList("s1"), Collections.singletonList("s2")),
-            Arrays.asList(
-                Collections.singletonList(TSDataType.DOUBLE),
-                Collections.singletonList(TSDataType.INT32)),
-            Arrays.asList(
-                Collections.singletonList(TSEncoding.RLE),
-                Collections.singletonList(TSEncoding.RLE)),
-            Arrays.asList(
-                Collections.singletonList(CompressionType.SNAPPY),
-                Collections.singletonList(CompressionType.SNAPPY)));
+            Arrays.asList("s1", "s2"),
+            Arrays.asList(TSDataType.DOUBLE, TSDataType.INT32),
+            Arrays.asList(TSEncoding.RLE, TSEncoding.RLE),
+            Arrays.asList(CompressionType.SNAPPY, CompressionType.SNAPPY));
     template.setId(templateId);
     schemaRegion.activateSchemaTemplate(
         SchemaRegionWritePlanFactory.getActivateTemplateInClusterPlan(
@@ -137,16 +131,10 @@ public class SchemaRegionTemplateTest extends AbstractSchemaRegionTest {
     Template template =
         new Template(
             "t1",
-            Arrays.asList(Collections.singletonList("s1"), Collections.singletonList("s2")),
-            Arrays.asList(
-                Collections.singletonList(TSDataType.DOUBLE),
-                Collections.singletonList(TSDataType.INT32)),
-            Arrays.asList(
-                Collections.singletonList(TSEncoding.RLE),
-                Collections.singletonList(TSEncoding.RLE)),
-            Arrays.asList(
-                Collections.singletonList(CompressionType.SNAPPY),
-                Collections.singletonList(CompressionType.SNAPPY)));
+            Arrays.asList("s1", "s2"),
+            Arrays.asList(TSDataType.DOUBLE, TSDataType.INT32),
+            Arrays.asList(TSEncoding.RLE, TSEncoding.RLE),
+            Arrays.asList(CompressionType.SNAPPY, CompressionType.SNAPPY));
     template.setId(templateId);
     schemaRegion.activateSchemaTemplate(
         SchemaRegionWritePlanFactory.getActivateTemplateInClusterPlan(
@@ -194,16 +182,10 @@ public class SchemaRegionTemplateTest extends AbstractSchemaRegionTest {
     Template template =
         new Template(
             "t1",
-            Arrays.asList(Collections.singletonList("s1"), Collections.singletonList("s2")),
-            Arrays.asList(
-                Collections.singletonList(TSDataType.DOUBLE),
-                Collections.singletonList(TSDataType.INT32)),
-            Arrays.asList(
-                Collections.singletonList(TSEncoding.RLE),
-                Collections.singletonList(TSEncoding.RLE)),
-            Arrays.asList(
-                Collections.singletonList(CompressionType.SNAPPY),
-                Collections.singletonList(CompressionType.SNAPPY)));
+            Arrays.asList("s1", "s2"),
+            Arrays.asList(TSDataType.DOUBLE, TSDataType.INT32),
+            Arrays.asList(TSEncoding.RLE, TSEncoding.RLE),
+            Arrays.asList(CompressionType.SNAPPY, CompressionType.SNAPPY));
     template.setId(templateId);
     schemaRegion.activateSchemaTemplate(
         SchemaRegionWritePlanFactory.getActivateTemplateInClusterPlan(
@@ -251,16 +233,10 @@ public class SchemaRegionTemplateTest extends AbstractSchemaRegionTest {
     Template template =
         new Template(
             "t1",
-            Arrays.asList(Collections.singletonList("s1"), Collections.singletonList("s2")),
-            Arrays.asList(
-                Collections.singletonList(TSDataType.DOUBLE),
-                Collections.singletonList(TSDataType.INT32)),
-            Arrays.asList(
-                Collections.singletonList(TSEncoding.RLE),
-                Collections.singletonList(TSEncoding.RLE)),
-            Arrays.asList(
-                Collections.singletonList(CompressionType.SNAPPY),
-                Collections.singletonList(CompressionType.SNAPPY)));
+            Arrays.asList("s1", "s2"),
+            Arrays.asList(TSDataType.DOUBLE, TSDataType.INT32),
+            Arrays.asList(TSEncoding.RLE, TSEncoding.RLE),
+            Arrays.asList(CompressionType.SNAPPY, CompressionType.SNAPPY));
     template.setId(templateId);
     schemaRegion.activateSchemaTemplate(
         SchemaRegionWritePlanFactory.getActivateTemplateInClusterPlan(