You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by wa...@apache.org on 2022/07/11 12:08:33 UTC

[iotdb] branch master updated: [IOTDB-3792] Show region tool support query condition of storage group (#6631)

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

wangchao316 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 0bc4e3dbb1 [IOTDB-3792] Show region tool support query condition of storage group (#6631)
0bc4e3dbb1 is described below

commit 0bc4e3dbb1f8007ad164da0131fda3d31201b0ff
Author: cmlmakahts <82...@users.noreply.github.com>
AuthorDate: Mon Jul 11 20:08:28 2022 +0800

    [IOTDB-3792] Show region tool support query condition of storage group (#6631)
    
    [IOTDB-3792] Show region tool support query condition of storage group (#6631)
---
 .../org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4   |  2 +-
 .../request/read/GetRegionInfoListPlan.java        | 40 ++++++++---
 .../confignode/persistence/ClusterSchemaInfo.java  |  2 +-
 .../persistence/executor/ConfigPlanExecutor.java   | 20 +++++-
 .../persistence/partition/PartitionInfo.java       |  7 ++
 .../partition/StorageGroupPartitionTable.java      |  6 +-
 .../thrift/ConfigNodeRPCServiceProcessor.java      |  3 +-
 .../request/ConfigPhysicalPlanSerDeTest.java       | 13 +++-
 .../confignode/persistence/PartitionInfoTest.java  | 79 +++++++++++++---------
 .../Maintenance-Tools/Maintenance-Command.md       | 56 +++++++++++++++
 .../Maintenance-Tools/Maintenance-Command.md       | 58 ++++++++++++++++
 .../config/executor/ClusterConfigTaskExecutor.java |  9 +++
 .../iotdb/db/mpp/plan/parser/ASTVisitor.java       | 13 ++++
 .../statement/metadata/ShowRegionStatement.java    | 19 +++++-
 .../src/main/thrift/confignode.thrift              |  1 +
 .../iotdb/tsfile/utils/ReadWriteIOUtils.java       | 13 ++++
 16 files changed, 291 insertions(+), 50 deletions(-)

diff --git a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4 b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
index e64e5c8be3..fe0add2da7 100644
--- a/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
+++ b/antlr/src/main/antlr4/org/apache/iotdb/db/qp/sql/IoTDBSqlParser.g4
@@ -310,7 +310,7 @@ showCluster
 
 // Show Region
 showRegion
-    : SHOW (SCHEMA | DATA)? REGIONS
+    : SHOW (SCHEMA | DATA)? REGIONS (OF STORAGE GROUP prefixPath? (COMMA prefixPath)*)?
     ;
 
 // Show Data Nodes
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/GetRegionInfoListPlan.java b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/GetRegionInfoListPlan.java
index d56edefc92..09b9199730 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/GetRegionInfoListPlan.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/consensus/request/read/GetRegionInfoListPlan.java
@@ -22,6 +22,7 @@ package org.apache.iotdb.confignode.consensus.request.read;
 import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
 import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlan;
 import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType;
+import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
 
 import java.io.DataOutputStream;
@@ -30,33 +31,54 @@ import java.nio.ByteBuffer;
 
 public class GetRegionInfoListPlan extends ConfigPhysicalPlan {
 
-  private TConsensusGroupType regionType;
+  private TShowRegionReq showRegionReq;
 
   public GetRegionInfoListPlan() {
     super(ConfigPhysicalPlanType.GetRegionInfoList);
   }
 
-  public GetRegionInfoListPlan(TConsensusGroupType regionType) {
+  public GetRegionInfoListPlan(TShowRegionReq showRegionReq) {
     super(ConfigPhysicalPlanType.GetRegionInfoList);
-    this.regionType = regionType;
+    this.showRegionReq = showRegionReq;
   }
 
-  public TConsensusGroupType getRegionType() {
-    return regionType;
+  public TShowRegionReq getShowRegionReq() {
+    return showRegionReq;
   }
 
-  public void setRegionType(TConsensusGroupType regionType) {
-    this.regionType = regionType;
+  public void setShowRegionReq(TShowRegionReq showRegionReq) {
+    this.showRegionReq = showRegionReq;
   }
 
   @Override
   protected void serializeImpl(DataOutputStream stream) throws IOException {
     stream.writeInt(getType().ordinal());
-    ReadWriteIOUtils.write(regionType.ordinal(), stream);
+    stream.writeBoolean(showRegionReq != null);
+    if (showRegionReq != null) {
+      boolean setConsensusGroupType = showRegionReq.isSetConsensusGroupType();
+      stream.writeBoolean(setConsensusGroupType);
+      if (setConsensusGroupType) {
+        ReadWriteIOUtils.write(showRegionReq.getConsensusGroupType().ordinal(), stream);
+      }
+      boolean setStorageGroups = showRegionReq.isSetStorageGroups();
+      stream.writeBoolean(setStorageGroups);
+      if (setStorageGroups) {
+        ReadWriteIOUtils.writeStringList(showRegionReq.getStorageGroups(), stream);
+      }
+    }
   }
 
   @Override
   protected void deserializeImpl(ByteBuffer buffer) throws IOException {
-    regionType = TConsensusGroupType.values()[ReadWriteIOUtils.readInt(buffer)];
+    if (ReadWriteIOUtils.readBool(buffer)) {
+      this.showRegionReq = new TShowRegionReq();
+      if (ReadWriteIOUtils.readBool(buffer)) {
+        this.showRegionReq.setConsensusGroupType(
+            TConsensusGroupType.values()[ReadWriteIOUtils.readInt(buffer)]);
+      }
+      if (ReadWriteIOUtils.readBool(buffer)) {
+        this.showRegionReq.setStorageGroups(ReadWriteIOUtils.readStringList(buffer));
+      }
+    }
   }
 }
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfo.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfo.java
index 6e6b7d604b..b910c8c00a 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfo.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/ClusterSchemaInfo.java
@@ -402,7 +402,7 @@ public class ClusterSchemaInfo implements SnapshotProcessor {
     try {
       for (String rawPath : rawPathList) {
         PartialPath patternPath = new PartialPath(rawPath);
-        List<PartialPath> matchedPaths = mTree.getBelongedStorageGroups(patternPath);
+        List<PartialPath> matchedPaths = mTree.getMatchedStorageGroups(patternPath, false);
         for (PartialPath path : matchedPaths) {
           schemaMap.put(
               path.getFullPath(), mTree.getStorageGroupNodeByPath(path).getStorageGroupSchema());
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
index 2f323911af..548d59c064 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/executor/ConfigPlanExecutor.java
@@ -60,6 +60,8 @@ import org.apache.iotdb.confignode.persistence.NodeInfo;
 import org.apache.iotdb.confignode.persistence.ProcedureInfo;
 import org.apache.iotdb.confignode.persistence.UDFInfo;
 import org.apache.iotdb.confignode.persistence.partition.PartitionInfo;
+import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
+import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchema;
 import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.Pair;
@@ -137,7 +139,7 @@ public class ConfigPlanExecutor {
       case GetNodePathsPartition:
         return getSchemaNodeManagementPartition(req);
       case GetRegionInfoList:
-        return partitionInfo.getRegionInfoList((GetRegionInfoListPlan) req);
+        return getRegionInfoList(req);
       case ShowSchemaTemplate:
         return clusterSchemaInfo.getAllTemplates();
       case ShowNodesInSchemaTemplate:
@@ -316,6 +318,22 @@ public class ConfigPlanExecutor {
     return schemaNodeManagementResp;
   }
 
+  private DataSet getRegionInfoList(ConfigPhysicalPlan req) {
+    final GetRegionInfoListPlan getRegionInfoListPlan = (GetRegionInfoListPlan) req;
+    TShowRegionReq showRegionReq = getRegionInfoListPlan.getShowRegionReq();
+    if (showRegionReq != null && showRegionReq.isSetStorageGroups()) {
+      final List<String> storageGroups = showRegionReq.getStorageGroups();
+      final List<String> matchedStorageGroups =
+          clusterSchemaInfo.getMatchedStorageGroupSchemasByName(storageGroups).values().stream()
+              .map(TStorageGroupSchema::getName)
+              .collect(Collectors.toList());
+      if (!matchedStorageGroups.isEmpty()) {
+        showRegionReq.setStorageGroups(matchedStorageGroups);
+      }
+    }
+    return partitionInfo.getRegionInfoList(getRegionInfoListPlan);
+  }
+
   private List<SnapshotProcessor> getAllAttributes() {
     List<SnapshotProcessor> allAttributes = new ArrayList<>();
     allAttributes.add(clusterSchemaInfo);
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java
index 90592cdbf2..d089ac3987 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java
@@ -44,6 +44,7 @@ import org.apache.iotdb.confignode.consensus.response.RegionInfoListResp;
 import org.apache.iotdb.confignode.consensus.response.SchemaNodeManagementResp;
 import org.apache.iotdb.confignode.consensus.response.SchemaPartitionResp;
 import org.apache.iotdb.confignode.exception.StorageGroupNotExistsException;
+import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
 import org.apache.iotdb.consensus.common.DataSet;
 import org.apache.iotdb.db.service.metrics.MetricsService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
@@ -426,8 +427,14 @@ public class PartitionInfo implements SnapshotProcessor {
       regionResp.setStatus(RpcUtils.getStatus(TSStatusCode.SUCCESS_STATUS));
       return regionResp;
     }
+    TShowRegionReq showRegionReq = regionsInfoPlan.getShowRegionReq();
+    final List<String> storageGroups =
+        showRegionReq != null ? showRegionReq.getStorageGroups() : null;
     storageGroupPartitionTables.forEach(
         (storageGroup, storageGroupPartitionTable) -> {
+          if (storageGroups != null && !storageGroups.contains(storageGroup)) {
+            return;
+          }
           storageGroupPartitionTable.getRegionInfoList(regionsInfoPlan, regionInfoList);
         });
     regionInfoList.sort(
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/StorageGroupPartitionTable.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/StorageGroupPartitionTable.java
index d584062ec6..0359b5c09f 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/StorageGroupPartitionTable.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/StorageGroupPartitionTable.java
@@ -29,6 +29,7 @@ import org.apache.iotdb.commons.cluster.RegionStatus;
 import org.apache.iotdb.commons.partition.DataPartitionTable;
 import org.apache.iotdb.commons.partition.SchemaPartitionTable;
 import org.apache.iotdb.confignode.consensus.request.read.GetRegionInfoListPlan;
+import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
 import org.apache.iotdb.db.service.metrics.MetricsService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
@@ -331,12 +332,13 @@ public class StorageGroupPartitionTable {
 
   public void getRegionInfoList(
       GetRegionInfoListPlan regionsInfoPlan, List<TRegionInfo> regionInfoList) {
+    final TShowRegionReq showRegionReq = regionsInfoPlan.getShowRegionReq();
     regionGroupMap.forEach(
         (consensusGroupId, regionGroup) -> {
           TRegionReplicaSet replicaSet = regionGroup.getReplicaSet();
-          if (regionsInfoPlan.getRegionType() == null) {
+          if (showRegionReq == null || showRegionReq.getConsensusGroupType() == null) {
             buildTRegionsInfo(regionInfoList, replicaSet, regionGroup);
-          } else if (regionsInfoPlan.getRegionType().ordinal()
+          } else if (regionsInfoPlan.getShowRegionReq().getConsensusGroupType().ordinal()
               == replicaSet.getRegionId().getType().ordinal()) {
             buildTRegionsInfo(regionInfoList, replicaSet, regionGroup);
           }
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
index 705417218a..6480f5f6fd 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
@@ -505,8 +505,7 @@ public class ConfigNodeRPCServiceProcessor implements IConfigNodeRPCService.Ifac
 
   @Override
   public TShowRegionResp showRegion(TShowRegionReq showRegionReq) throws TException {
-    GetRegionInfoListPlan getRegionInfoListPlan =
-        new GetRegionInfoListPlan(showRegionReq.getConsensusGroupType());
+    GetRegionInfoListPlan getRegionInfoListPlan = new GetRegionInfoListPlan(showRegionReq);
     RegionInfoListResp dataSet =
         (RegionInfoListResp) configManager.showRegion(getRegionInfoListPlan);
     TShowRegionResp showRegionResp = new TShowRegionResp();
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 8f35519eb4..981af7d1cb 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
@@ -64,6 +64,7 @@ import org.apache.iotdb.confignode.consensus.request.write.SetTimePartitionInter
 import org.apache.iotdb.confignode.consensus.request.write.UpdateProcedurePlan;
 import org.apache.iotdb.confignode.procedure.Procedure;
 import org.apache.iotdb.confignode.procedure.impl.DeleteStorageGroupProcedure;
+import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
 import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchema;
 import org.apache.iotdb.db.metadata.template.Template;
 import org.apache.iotdb.db.mpp.plan.statement.metadata.template.CreateSchemaTemplateStatement;
@@ -596,11 +597,19 @@ public class ConfigPhysicalPlanSerDeTest {
   @Test
   public void GetRegionLocaltionsPlanTest() throws IOException {
     GetRegionInfoListPlan req0 = new GetRegionInfoListPlan();
-    req0.setRegionType(TConsensusGroupType.DataRegion);
+    TShowRegionReq showRegionReq = new TShowRegionReq();
+    req0.setShowRegionReq(showRegionReq);
+    showRegionReq.setConsensusGroupType(TConsensusGroupType.DataRegion);
     GetRegionInfoListPlan req1 =
         (GetRegionInfoListPlan) ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
     Assert.assertEquals(req0.getType(), req1.getType());
-    Assert.assertEquals(req0.getRegionType(), req1.getRegionType());
+    Assert.assertEquals(req0.getShowRegionReq(), req1.getShowRegionReq());
+    final List<String> sgList = Collections.singletonList("root.sg1, root.sg2, root.*");
+    showRegionReq.setStorageGroups(new ArrayList<>(sgList));
+    GetRegionInfoListPlan req2 =
+        (GetRegionInfoListPlan) ConfigPhysicalPlan.Factory.create(req0.serializeToByteBuffer());
+    Assert.assertEquals(req0.getType(), req1.getType());
+    Assert.assertEquals(req0.getShowRegionReq(), req2.getShowRegionReq());
   }
 
   @Test
diff --git a/confignode/src/test/java/org/apache/iotdb/confignode/persistence/PartitionInfoTest.java b/confignode/src/test/java/org/apache/iotdb/confignode/persistence/PartitionInfoTest.java
index c813dc772d..c97081abb2 100644
--- a/confignode/src/test/java/org/apache/iotdb/confignode/persistence/PartitionInfoTest.java
+++ b/confignode/src/test/java/org/apache/iotdb/confignode/persistence/PartitionInfoTest.java
@@ -36,6 +36,7 @@ import org.apache.iotdb.confignode.consensus.request.write.CreateSchemaPartition
 import org.apache.iotdb.confignode.consensus.request.write.SetStorageGroupPlan;
 import org.apache.iotdb.confignode.consensus.response.RegionInfoListResp;
 import org.apache.iotdb.confignode.persistence.partition.PartitionInfo;
+import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
 import org.apache.iotdb.confignode.rpc.thrift.TStorageGroupSchema;
 
 import org.apache.commons.io.FileUtils;
@@ -147,36 +148,40 @@ public class PartitionInfoTest {
 
   @Test
   public void testShowRegion() {
-    partitionInfo.generateNextRegionGroupId();
-
-    // Set StorageGroup
-    partitionInfo.setStorageGroup(new SetStorageGroupPlan(new TStorageGroupSchema("root.test")));
-
-    // Create a SchemaRegion
-    CreateRegionGroupsPlan createRegionGroupsPlan = new CreateRegionGroupsPlan();
-    TRegionReplicaSet schemaRegionReplicaSet =
-        generateTRegionReplicaSet(
-            testFlag.SchemaPartition.getFlag(),
-            generateTConsensusGroupId(
-                testFlag.SchemaPartition.getFlag(), TConsensusGroupType.SchemaRegion));
-    createRegionGroupsPlan.addRegionGroup("root.test", schemaRegionReplicaSet);
-    partitionInfo.createRegionGroups(createRegionGroupsPlan);
-
-    // Create a DataRegion
-    createRegionGroupsPlan = new CreateRegionGroupsPlan();
-    TRegionReplicaSet dataRegionReplicaSet =
-        generateTRegionReplicaSet(
-            testFlag.DataPartition.getFlag(),
-            generateTConsensusGroupId(
-                testFlag.DataPartition.getFlag(), TConsensusGroupType.DataRegion));
-    createRegionGroupsPlan.addRegionGroup("root.test", dataRegionReplicaSet);
-    partitionInfo.createRegionGroups(createRegionGroupsPlan);
-
+    for (int i = 0; i < 2; i++) {
+      partitionInfo.generateNextRegionGroupId();
+
+      // Set StorageGroup
+      partitionInfo.setStorageGroup(
+          new SetStorageGroupPlan(new TStorageGroupSchema("root.test" + i)));
+
+      // Create a SchemaRegion
+      CreateRegionGroupsPlan createRegionGroupsPlan = new CreateRegionGroupsPlan();
+      TRegionReplicaSet schemaRegionReplicaSet =
+          generateTRegionReplicaSet(
+              testFlag.SchemaPartition.getFlag(),
+              generateTConsensusGroupId(
+                  testFlag.SchemaPartition.getFlag(), TConsensusGroupType.SchemaRegion));
+      createRegionGroupsPlan.addRegionGroup("root.test" + i, schemaRegionReplicaSet);
+      partitionInfo.createRegionGroups(createRegionGroupsPlan);
+
+      // Create a DataRegion
+      createRegionGroupsPlan = new CreateRegionGroupsPlan();
+      TRegionReplicaSet dataRegionReplicaSet =
+          generateTRegionReplicaSet(
+              testFlag.DataPartition.getFlag(),
+              generateTConsensusGroupId(
+                  testFlag.DataPartition.getFlag(), TConsensusGroupType.DataRegion));
+      createRegionGroupsPlan.addRegionGroup("root.test" + i, dataRegionReplicaSet);
+      partitionInfo.createRegionGroups(createRegionGroupsPlan);
+    }
     GetRegionInfoListPlan regionReq = new GetRegionInfoListPlan();
-    regionReq.setRegionType(null);
+    TShowRegionReq showRegionReq = new TShowRegionReq();
+    showRegionReq.setConsensusGroupType(null);
+    regionReq.setShowRegionReq(showRegionReq);
     RegionInfoListResp regionInfoList1 =
         (RegionInfoListResp) partitionInfo.getRegionInfoList(regionReq);
-    Assert.assertEquals(regionInfoList1.getRegionInfoList().size(), 10);
+    Assert.assertEquals(regionInfoList1.getRegionInfoList().size(), 20);
     regionInfoList1
         .getRegionInfoList()
         .forEach(
@@ -184,10 +189,10 @@ public class PartitionInfoTest {
               Assert.assertEquals(regionInfo.getClientRpcIp(), "127.0.0.1");
             });
 
-    regionReq.setRegionType(TConsensusGroupType.SchemaRegion);
+    showRegionReq.setConsensusGroupType(TConsensusGroupType.SchemaRegion);
     RegionInfoListResp regionInfoList2 =
         (RegionInfoListResp) partitionInfo.getRegionInfoList(regionReq);
-    Assert.assertEquals(regionInfoList2.getRegionInfoList().size(), 5);
+    Assert.assertEquals(regionInfoList2.getRegionInfoList().size(), 10);
     regionInfoList2
         .getRegionInfoList()
         .forEach(
@@ -196,10 +201,10 @@ public class PartitionInfoTest {
                   regionInfo.getConsensusGroupId().getType(), TConsensusGroupType.SchemaRegion);
             });
 
-    regionReq.setRegionType(TConsensusGroupType.DataRegion);
+    showRegionReq.setConsensusGroupType(TConsensusGroupType.DataRegion);
     RegionInfoListResp regionInfoList3 =
         (RegionInfoListResp) partitionInfo.getRegionInfoList(regionReq);
-    Assert.assertEquals(regionInfoList3.getRegionInfoList().size(), 5);
+    Assert.assertEquals(regionInfoList3.getRegionInfoList().size(), 10);
     regionInfoList3
         .getRegionInfoList()
         .forEach(
@@ -207,6 +212,18 @@ public class PartitionInfoTest {
               Assert.assertEquals(
                   regionInfo.getConsensusGroupId().getType(), TConsensusGroupType.DataRegion);
             });
+    showRegionReq.setConsensusGroupType(null);
+    showRegionReq.setStorageGroups(Collections.singletonList("root.test1"));
+    RegionInfoListResp regionInfoList4 =
+        (RegionInfoListResp) partitionInfo.getRegionInfoList(regionReq);
+    Assert.assertEquals(regionInfoList4.getRegionInfoList().size(), 10);
+    regionInfoList4
+        .getRegionInfoList()
+        .forEach(
+            (regionInfo) -> {
+              Assert.assertEquals(regionInfo.getClientRpcIp(), "127.0.0.1");
+              Assert.assertEquals(regionInfo.getStorageGroup(), "root.test1");
+            });
   }
 
   private TRegionReplicaSet generateTRegionReplicaSet(
diff --git a/docs/UserGuide/Maintenance-Tools/Maintenance-Command.md b/docs/UserGuide/Maintenance-Tools/Maintenance-Command.md
index 5698c7c8a0..7af95a5a2e 100644
--- a/docs/UserGuide/Maintenance-Tools/Maintenance-Command.md
+++ b/docs/UserGuide/Maintenance-Tools/Maintenance-Command.md
@@ -128,6 +128,7 @@ Currently, IoTDB supports Region query using the following SQL:
 - `SHOW REGIONS`: Show all Region
 - `SHOW SCHEMA REGIONS`: Show all SchemaRegion distribution
 - `SHOW DATA REGIONS`: Show all DataRegion distribution
+- `SHOW (DATA|SCHEMA)? REGIONS OF STORAGE GROUP <sg1,sg2,...>`: Show region distribution of specified storage groups
 
 ```sql
 IoTDB> create timeseries root.sg.d1.s1 with datatype=BOOLEAN,encoding=PLAIN
@@ -179,6 +180,61 @@ IoTDB> show schema regions
 +--------+------------+------+-------------+------------+----------+----------+---------+----+
 Total line number = 2
 It costs 0.012s
+    
+IoTDB> show regions of storage group root.sg1
+show regions of storage group root.sg1
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+|RegionId|        Type|Status|storage group|Series Slots|Time Slots|DataNodeId|     Host|Port|
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+|      10|SchemaRegion|    Up|     root.sg1|           1|         0|         4|127.0.0.1|6669|
+|      11|  DataRegion|    Up|     root.sg1|           1|         1|         5|127.0.0.1|6671|
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+Total line number = 2
+It costs 0.005s
+
+IoTDB> show regions of storage group root.sg1, root.sg2
+show regions of storage group root.sg1, root.sg2
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+|RegionId|        Type|Status|storage group|Series Slots|Time Slots|DataNodeId|     Host|Port|
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+|      10|SchemaRegion|    Up|     root.sg1|           1|         0|         4|127.0.0.1|6669|
+|      11|  DataRegion|    Up|     root.sg1|           1|         1|         5|127.0.0.1|6671|
+|      12|SchemaRegion|    Up|     root.sg2|           1|         0|         4|127.0.0.1|6669|
+|      13|  DataRegion|    Up|     root.sg2|           1|         1|         4|127.0.0.1|6669|
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+Total line number = 4
+It costs 0.005s
+
+IoTDB> show regions of storage group root.*.sg_2
+show regions of storage group root.*.sg_2
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+|RegionId|        Type|Status| storage group|Series Slots|Time Slots|DataNodeId|     Host|Port|
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+|      14|SchemaRegion|    Up|root.sg_1.sg_2|           1|         0|         3|127.0.0.1|6667|
+|      15|  DataRegion|    Up|root.sg_1.sg_2|           1|         1|         5|127.0.0.1|6671|
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+Total line number = 2
+It costs 0.004s
+
+IoTDB> show data regions of storage group root.*.sg_2
+show data regions of storage group root.*.sg_2
++--------+----------+------+--------------+------------+----------+----------+---------+----+
+|RegionId|      Type|Status| storage group|Series Slots|Time Slots|DataNodeId|     Host|Port|
++--------+----------+------+--------------+------------+----------+----------+---------+----+
+|      15|DataRegion|    Up|root.sg_1.sg_2|           1|         1|         5|127.0.0.1|6671|
++--------+----------+------+--------------+------------+----------+----------+---------+----+
+Total line number = 1
+It costs 0.004s
+
+IoTDB> show schema regions of storage group root.*.sg_2
+show schema regions of storage group root.*.sg_2
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+|RegionId|        Type|Status| storage group|Series Slots|Time Slots|DataNodeId|     Host|Port|
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+|       14|SchemaRegion|    Up|root.sg_1.sg_2|           1|         0|         5|127.0.0.1|6671|
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+Total line number = 1
+It costs 0.102s
 ```
 ## Monitoring tool for cluster Node distribution
 
diff --git a/docs/zh/UserGuide/Maintenance-Tools/Maintenance-Command.md b/docs/zh/UserGuide/Maintenance-Tools/Maintenance-Command.md
index e43a3a5909..b55277426b 100644
--- a/docs/zh/UserGuide/Maintenance-Tools/Maintenance-Command.md
+++ b/docs/zh/UserGuide/Maintenance-Tools/Maintenance-Command.md
@@ -123,6 +123,8 @@ KILL QUERY <queryId>
 - `SHOW REGIONS`: 展示所有 Region
 - `SHOW SCHEMA REGIONS`: 展示所有 SchemaRegion 分布
 - `SHOW DATA REGIONS`: 展示所有 DataRegion 分布
+- `SHOW (DATA|SCHEMA)? REGIONS OF STORAGE GROUP <sg1,sg2,...>`: 展示指定的存储组<sg1,sg2,...>对应的Region分布
+
 
 ```sql
 IoTDB> create timeseries root.sg.d1.s1 with datatype=BOOLEAN,encoding=PLAIN
@@ -174,6 +176,62 @@ IoTDB> show schema regions
 +--------+------------+------+-------------+------------+----------+----------+---------+----+
 Total line number = 2
 It costs 0.012s
+
+IoTDB> show regions of storage group root.sg1
+show regions of storage group root.sg1
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+|RegionId|        Type|Status|storage group|Series Slots|Time Slots|DataNodeId|     Host|Port|
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+|      10|SchemaRegion|    Up|     root.sg1|           1|         0|         4|127.0.0.1|6669|
+|      11|  DataRegion|    Up|     root.sg1|           1|         1|         5|127.0.0.1|6671|
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+Total line number = 2
+It costs 0.005s
+
+IoTDB> show regions of storage group root.sg1, root.sg2
+show regions of storage group root.sg1, root.sg2
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+|RegionId|        Type|Status|storage group|Series Slots|Time Slots|DataNodeId|     Host|Port|
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+|      10|SchemaRegion|    Up|     root.sg1|           1|         0|         4|127.0.0.1|6669|
+|      11|  DataRegion|    Up|     root.sg1|           1|         1|         5|127.0.0.1|6671|
+|      12|SchemaRegion|    Up|     root.sg2|           1|         0|         4|127.0.0.1|6669|
+|      13|  DataRegion|    Up|     root.sg2|           1|         1|         4|127.0.0.1|6669|
++--------+------------+------+-------------+------------+----------+----------+---------+----+
+Total line number = 4
+It costs 0.005s
+
+IoTDB> show regions of storage group root.*.sg_2
+show regions of storage group root.*.sg_2
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+|RegionId|        Type|Status| storage group|Series Slots|Time Slots|DataNodeId|     Host|Port|
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+|      14|SchemaRegion|    Up|root.sg_1.sg_2|           1|         0|         3|127.0.0.1|6667|
+|      15|  DataRegion|    Up|root.sg_1.sg_2|           1|         1|         5|127.0.0.1|6671|
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+Total line number = 2
+It costs 0.004s
+
+IoTDB> show data regions of storage group root.*.sg_2
+show data regions of storage group root.*.sg_2
++--------+----------+------+--------------+------------+----------+----------+---------+----+
+|RegionId|      Type|Status| storage group|Series Slots|Time Slots|DataNodeId|     Host|Port|
++--------+----------+------+--------------+------------+----------+----------+---------+----+
+|      15|DataRegion|    Up|root.sg_1.sg_2|           1|         1|         5|127.0.0.1|6671|
++--------+----------+------+--------------+------------+----------+----------+---------+----+
+Total line number = 1
+It costs 0.004s
+
+
+IoTDB> show schema regions of storage group root.*.sg_2
+show schema regions of storage group root.*.sg_2
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+|RegionId|        Type|Status| storage group|Series Slots|Time Slots|DataNodeId|     Host|Port|
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+|       14|SchemaRegion|    Up|root.sg_1.sg_2|           1|         0|         5|127.0.0.1|6671|
++--------+------------+------+--------------+------------+----------+----------+---------+----+
+Total line number = 1
+It costs 0.102s
 ```
 ## 集群节点分布式监控工具
 
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java
index 0d04cf2792..1ff880d900 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/config/executor/ClusterConfigTaskExecutor.java
@@ -77,6 +77,7 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 public class ClusterConfigTaskExecutor implements IConfigTaskExecutor {
 
@@ -338,6 +339,14 @@ public class ClusterConfigTaskExecutor implements IConfigTaskExecutor {
     TShowRegionResp showRegionResp = new TShowRegionResp();
     TShowRegionReq showRegionReq = new TShowRegionReq();
     showRegionReq.setConsensusGroupType(showRegionStatement.getRegionType());
+    if (showRegionStatement.getStorageGroups() == null) {
+      showRegionReq.setStorageGroups(null);
+    } else {
+      showRegionReq.setStorageGroups(
+          showRegionStatement.getStorageGroups().stream()
+              .map(PartialPath::getFullPath)
+              .collect(Collectors.toList()));
+    }
     try (ConfigNodeClient client =
         CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.partitionRegionId)) {
       showRegionResp = client.showRegion(showRegionReq);
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 7aa614fac7..f04d2516f7 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
@@ -2305,6 +2305,19 @@ public class ASTVisitor extends IoTDBSqlParserBaseVisitor<Statement> {
     } else {
       showRegionStatement.setRegionType(null);
     }
+
+    if (ctx.OF() != null) {
+      List<PartialPath> storageGroups = null;
+      if (ctx.prefixPath(0) != null) {
+        storageGroups = new ArrayList<>();
+        for (IoTDBSqlParser.PrefixPathContext prefixPathContext : ctx.prefixPath()) {
+          storageGroups.add(parsePrefixPath(prefixPathContext));
+        }
+      }
+      showRegionStatement.setStorageGroups(storageGroups);
+    } else {
+      showRegionStatement.setStorageGroups(null);
+    }
     return showRegionStatement;
   }
 
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/ShowRegionStatement.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/ShowRegionStatement.java
index 42f690856b..09f0e7b54b 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/ShowRegionStatement.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/statement/metadata/ShowRegionStatement.java
@@ -20,19 +20,36 @@
 package org.apache.iotdb.db.mpp.plan.statement.metadata;
 
 import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType;
+import org.apache.iotdb.commons.path.PartialPath;
 import org.apache.iotdb.db.mpp.plan.analyze.QueryType;
 import org.apache.iotdb.db.mpp.plan.statement.IConfigStatement;
 import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
 
+import java.util.List;
+
 public class ShowRegionStatement extends ShowStatement implements IConfigStatement {
 
+  private TConsensusGroupType regionType;
+  private List<PartialPath> storageGroups;
+
   public ShowRegionStatement() {}
 
   public ShowRegionStatement(TConsensusGroupType regionType) {
     this.regionType = regionType;
   }
 
-  private TConsensusGroupType regionType;
+  public ShowRegionStatement(TConsensusGroupType regionType, List<PartialPath> storageGroups) {
+    this.regionType = regionType;
+    this.storageGroups = storageGroups;
+  }
+
+  public List<PartialPath> getStorageGroups() {
+    return storageGroups;
+  }
+
+  public void setStorageGroups(List<PartialPath> storageGroups) {
+    this.storageGroups = storageGroups;
+  }
 
   public TConsensusGroupType getRegionType() {
     return regionType;
diff --git a/thrift-confignode/src/main/thrift/confignode.thrift b/thrift-confignode/src/main/thrift/confignode.thrift
index 4ee1753aaa..787ebd062f 100644
--- a/thrift-confignode/src/main/thrift/confignode.thrift
+++ b/thrift-confignode/src/main/thrift/confignode.thrift
@@ -242,6 +242,7 @@ struct TDropFunctionReq {
 // show regions
 struct TShowRegionReq {
   1: optional common.TConsensusGroupType consensusGroupType;
+  2: optional list<string> storageGroups
 }
 
 struct TShowRegionResp {
diff --git a/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtils.java b/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtils.java
index 5fa9b9346e..dfa6be3f55 100644
--- a/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtils.java
+++ b/tsfile/src/main/java/org/apache/iotdb/tsfile/utils/ReadWriteIOUtils.java
@@ -815,6 +815,19 @@ public class ReadWriteIOUtils {
     }
   }
 
+  /** write string list with self define length. */
+  public static void writeStringList(List<String> list, OutputStream outputStream)
+      throws IOException {
+    if (list == null) {
+      throw new IllegalArgumentException("stringList must not be null!");
+    }
+    int size = list.size();
+    write(size, outputStream);
+    for (String s : list) {
+      write(s, outputStream);
+    }
+  }
+
   public static CompressionType readCompressionType(InputStream inputStream) throws IOException {
     byte n = readByte(inputStream);
     return CompressionType.deserialize(n);