diff --git a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java index 463a9f7e8b665..0d110ddcff81c 100644 --- a/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java +++ b/integration-test/src/test/java/org/apache/iotdb/relational/it/schema/IoTDBDatabaseIT.java @@ -138,6 +138,9 @@ public void testManageDatabase() { assertEquals(databaseNames.length, cnt); } + TestUtils.assertResultSetEqual( + statement.executeQuery("count databases"), "count,", Collections.singleton("2,")); + final int[] schemaRegionGroupNum = new int[] {0}; final int[] dataRegionGroupNum = new int[] {0}; // show diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionMetrics.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionMetrics.java index b6b709cd8010d..4d2f4e9c4f588 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionMetrics.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/partition/PartitionMetrics.java @@ -22,14 +22,18 @@ import org.apache.iotdb.common.rpc.thrift.TConsensusGroupType; import org.apache.iotdb.common.rpc.thrift.TDataNodeConfiguration; import org.apache.iotdb.commons.cluster.RegionStatus; +import org.apache.iotdb.commons.schema.table.InformationSchema; +import org.apache.iotdb.commons.schema.table.TableType; import org.apache.iotdb.commons.service.metric.enums.Metric; import org.apache.iotdb.commons.service.metric.enums.Tag; import org.apache.iotdb.commons.utils.NodeUrlUtils; +import org.apache.iotdb.commons.utils.PathUtils; import org.apache.iotdb.confignode.exception.DatabaseNotExistsException; import org.apache.iotdb.confignode.manager.IManager; import org.apache.iotdb.confignode.manager.load.LoadManager; import org.apache.iotdb.confignode.manager.node.NodeManager; import org.apache.iotdb.confignode.manager.schema.ClusterSchemaManager; +import org.apache.iotdb.confignode.persistence.schema.ConfigSchemaStatistics; import org.apache.iotdb.metrics.AbstractMetricService; import org.apache.iotdb.metrics.metricsets.IMetricSet; import org.apache.iotdb.metrics.utils.MetricLevel; @@ -267,18 +271,34 @@ private void unbindRegionPartitionMetrics(AbstractMetricService metricService) { // region Database Partition Metrics - private void bindDatabaseRelatedMetrics(AbstractMetricService metricService) { - ClusterSchemaManager clusterSchemaManager = getClusterSchemaManager(); + private void bindDatabaseRelatedMetrics(final AbstractMetricService metricService) { + final ClusterSchemaManager clusterSchemaManager = getClusterSchemaManager(); + final ConfigSchemaStatistics statistics = clusterSchemaManager.getConfigSchemaStatistics(); // Count the number of Databases metricService.createAutoGauge( Metric.DATABASE_NUM.toString(), MetricLevel.CORE, - clusterSchemaManager, - // Add 1 for information schema - c -> c.getDatabaseNames(null).size() + 1); + statistics, + s -> s.getTableDatabaseNum() + s.getTreeDatabaseNum()); + metricService.createAutoGauge( + Metric.TABLE_DATABASE_NUM.toString(), + MetricLevel.CORE, + statistics, + ConfigSchemaStatistics::getTableDatabaseNum); - List databases = clusterSchemaManager.getDatabaseNames(null); - for (String database : databases) { + // Enable table num gauge for information_schema + metricService + .getOrCreateGauge( + Metric.TABLE_NUM.toString(), + MetricLevel.CORE, + Tag.TYPE.toString(), + TableType.SYSTEM_VIEW.getName(), + Tag.DATABASE.toString(), + InformationSchema.INFORMATION_DATABASE) + .set(InformationSchema.getSchemaTables().size()); + + final List databases = clusterSchemaManager.getDatabaseNames(null); + for (final String database : databases) { int dataReplicationFactor = 1; int schemaReplicationFactor = 1; try { @@ -291,16 +311,28 @@ private void bindDatabaseRelatedMetrics(AbstractMetricService metricService) { } bindDatabaseRelatedMetricsWhenUpdate( metricService, configManager, database, dataReplicationFactor, schemaReplicationFactor); + bindDatabaseTableMetrics(metricService, statistics, database); } } private void unbindDatabaseRelatedMetrics(AbstractMetricService metricService) { // Remove the number of Databases metricService.remove(MetricType.AUTO_GAUGE, Metric.DATABASE_NUM.toString()); + metricService.remove(MetricType.AUTO_GAUGE, Metric.TABLE_DATABASE_NUM.toString()); + + // Remove gauge for information_schema + metricService.remove( + MetricType.GAUGE, + Metric.TABLE_NUM.toString(), + Tag.TYPE.toString(), + TableType.SYSTEM_VIEW.getName(), + Tag.DATABASE.toString(), + InformationSchema.INFORMATION_DATABASE); List databases = getClusterSchemaManager().getDatabaseNames(null); for (String database : databases) { unbindDatabaseRelatedMetricsWhenUpdate(metricService, database); + unbindDatabaseTableMetrics(metricService, database); } } @@ -446,6 +478,54 @@ public static void bindDatabaseReplicationFactorMetricsWhenUpdate( .set(schemaReplicationFactor); } + public static void bindDatabaseTableMetrics( + final AbstractMetricService metricService, + final ConfigSchemaStatistics statistics, + final String database) { + if (!PathUtils.isTableModelDatabase(database)) { + return; + } + metricService.createAutoGauge( + Metric.TABLE_NUM.toString(), + MetricLevel.CORE, + statistics, + s -> s.getTreeViewTableNum(database), + Tag.TYPE.toString(), + TableType.VIEW_FROM_TREE.getName(), + Tag.DATABASE.toString(), + database); + metricService.createAutoGauge( + Metric.TABLE_NUM.toString(), + MetricLevel.CORE, + statistics, + s -> s.getBaseTableNum(database), + Tag.TYPE.toString(), + TableType.BASE_TABLE.getName(), + Tag.DATABASE.toString(), + database); + } + + public static void unbindDatabaseTableMetrics( + final AbstractMetricService metricService, final String database) { + if (!PathUtils.isTableModelDatabase(database)) { + return; + } + metricService.remove( + MetricType.AUTO_GAUGE, + Metric.TABLE_NUM.toString(), + Tag.TYPE.toString(), + TableType.VIEW_FROM_TREE.getName(), + Tag.DATABASE.toString(), + database); + metricService.remove( + MetricType.AUTO_GAUGE, + Metric.TABLE_NUM.toString(), + Tag.TYPE.toString(), + TableType.BASE_TABLE.getName(), + Tag.DATABASE.toString(), + database); + } + // endregion private NodeManager getNodeManager() { diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java index 9a04d9e9e59b7..95d72edba9527 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/manager/schema/ClusterSchemaManager.java @@ -89,6 +89,7 @@ import org.apache.iotdb.confignode.manager.partition.PartitionManager; import org.apache.iotdb.confignode.manager.partition.PartitionMetrics; import org.apache.iotdb.confignode.persistence.schema.ClusterSchemaInfo; +import org.apache.iotdb.confignode.persistence.schema.ConfigSchemaStatistics; import org.apache.iotdb.confignode.rpc.thrift.TDatabaseInfo; import org.apache.iotdb.confignode.rpc.thrift.TDatabaseSchema; import org.apache.iotdb.confignode.rpc.thrift.TDescTable4InformationSchemaResp; @@ -198,6 +199,10 @@ public TSStatus setDatabase( schema.getName(), schema.getDataReplicationFactor(), schema.getSchemaReplicationFactor()); + PartitionMetrics.bindDatabaseTableMetrics( + MetricService.getInstance(), + clusterSchemaInfo.getConfigSchemaStatistics(), + schema.getName()); // Adjust the maximum RegionGroup number of each Database adjustMaxRegionGroupNum(); } catch (final ConsensusException e) { @@ -615,6 +620,10 @@ public List getDatabaseNames(final Boolean isTableModel) { .collect(Collectors.toList()); } + public ConfigSchemaStatistics getConfigSchemaStatistics() { + return clusterSchemaInfo.getConfigSchemaStatistics(); + } + /** * Only leader use this interface. Get the specified Database's schemaengine * diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java index 376fd29e1e7f7..e7bd4261aed4b 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/CNPhysicalPlanGenerator.java @@ -475,7 +475,7 @@ private void generateDatabasePhysicalPlan() { name = internalMNode.getName(); break; case DATABASE_MNODE_TYPE: - databaseMNode = deserializeDatabaseMNode(bufferedInputStream).getAsMNode(); + databaseMNode = deserializeDatabaseMNode(bufferedInputStream); while (!stack.isEmpty() && !stack.peek().right) { databaseMNode.addChild(stack.pop().left); } diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java index 1fc4b04c2b604..7882d5b2e69f3 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ClusterSchemaInfo.java @@ -37,6 +37,7 @@ import org.apache.iotdb.commons.utils.PathUtils; import org.apache.iotdb.commons.utils.StatusUtils; import org.apache.iotdb.commons.utils.TestOnly; +import org.apache.iotdb.confignode.consensus.request.ConfigPhysicalPlanType; import org.apache.iotdb.confignode.consensus.request.read.database.CountDatabasePlan; import org.apache.iotdb.confignode.consensus.request.read.database.GetDatabasePlan; import org.apache.iotdb.confignode.consensus.request.read.table.DescTablePlan; @@ -151,6 +152,7 @@ public class ClusterSchemaInfo implements SnapshotProcessor { private final ReentrantReadWriteLock databaseReadWriteLock; private final ConfigMTree treeModelMTree; private final ConfigMTree tableModelMTree; + private final ConfigSchemaStatistics configSchemaStatistics; private static final String TREE_SNAPSHOT_FILENAME = "cluster_schema.bin"; private static final String TABLE_SNAPSHOT_FILENAME = "table_cluster_schema.bin"; @@ -166,6 +168,7 @@ public ClusterSchemaInfo() throws IOException { try { treeModelMTree = new ConfigMTree(false); tableModelMTree = new ConfigMTree(true); + configSchemaStatistics = new ConfigSchemaStatistics(); templateTable = new TemplateTable(); templatePreSetTable = new TemplatePreSetTable(); } catch (final MetadataException e) { @@ -201,6 +204,12 @@ public TSStatus createDatabase(final DatabaseSchemaPlan plan) { .getAsMNode() .setDatabaseSchema(databaseSchema); + if (databaseSchema.isIsTableModel()) { + configSchemaStatistics.increaseTableDatabaseNum(); + } else { + configSchemaStatistics.increaseTreeDatabaseNum(); + } + result.setCode(TSStatusCode.SUCCESS_STATUS.getStatusCode()); } catch (final MetadataException e) { LOGGER.error(ERROR_NAME, e); @@ -301,6 +310,12 @@ public TSStatus deleteDatabase(final DeleteDatabasePlan plan) { (isTableModel ? tableModelMTree : treeModelMTree) .deleteDatabase(getQualifiedDatabasePartialPath(plan.getName())); + if (isTableModel) { + configSchemaStatistics.decreaseTableDatabaseNum(); + } else { + configSchemaStatistics.decreaseTreeDatabaseNum(); + } + result.setCode(TSStatusCode.SUCCESS_STATUS.getStatusCode()); } catch (final MetadataException e) { LOGGER.warn("Database not exist", e); @@ -785,14 +800,14 @@ public void processLoadSnapshot(final File snapshotDir) throws IOException { TREE_SNAPSHOT_FILENAME, stream -> { treeModelMTree.clear(); - treeModelMTree.deserialize(stream); + treeModelMTree.deserialize(stream, configSchemaStatistics); }); processMTreeLoadSnapshot( snapshotDir, TABLE_SNAPSHOT_FILENAME, stream -> { tableModelMTree.clear(); - tableModelMTree.deserialize(stream); + tableModelMTree.deserialize(stream, configSchemaStatistics); }); templateTable.processLoadSnapshot(snapshotDir); templatePreSetTable.processLoadSnapshot(snapshotDir); @@ -1168,25 +1183,42 @@ public TSStatus extendSchemaTemplate(ExtendSchemaTemplatePlan extendSchemaTempla public TSStatus preCreateTable(final PreCreateTablePlan plan) { return executeWithLock( - () -> - tableModelMTree.preCreateTable( - getQualifiedDatabasePartialPath(plan.getDatabase()), plan.getTable())); + () -> { + tableModelMTree.preCreateTable( + getQualifiedDatabasePartialPath(plan.getDatabase()), plan.getTable()); + configSchemaStatistics.increaseBaseTableNum(plan.getDatabase()); + }); } public TSStatus preCreateTableView(final PreCreateTableViewPlan plan) { return executeWithLock( - () -> - tableModelMTree.preCreateTableView( - getQualifiedDatabasePartialPath(plan.getDatabase()), - plan.getTable(), - plan.getStatus())); + () -> { + tableModelMTree.preCreateTableView( + getQualifiedDatabasePartialPath(plan.getDatabase()), + plan.getTable(), + plan.getStatus()); + configSchemaStatistics.increaseTreeViewTableNum(plan.getDatabase()); + }); } public TSStatus rollbackCreateTable(final RollbackCreateTablePlan plan) { return executeWithLock( - () -> - tableModelMTree.rollbackCreateTable( - getQualifiedDatabasePartialPath(plan.getDatabase()), plan.getTableName())); + () -> { + final PartialPath database = getQualifiedDatabasePartialPath(plan.getDatabase()); + final String tableName = plan.getTableName(); + tableModelMTree + .getTableAndStatusIfExists(database, tableName) + .map(Pair::getLeft) + .ifPresent( + table -> { + if (TreeViewSchema.isTreeViewTable(table)) { + configSchemaStatistics.decreaseTreeViewTableNum(tableName); + } else { + configSchemaStatistics.decreaseBaseTableNum(tableName); + } + }); + tableModelMTree.rollbackCreateTable(database, tableName); + }); } public TSStatus commitCreateTable(final CommitCreateTablePlan plan) { @@ -1207,9 +1239,15 @@ public TSStatus preDeleteTable(final PreDeleteTablePlan plan) { public TSStatus dropTable(final CommitDeleteTablePlan plan) { return executeWithLock( - () -> - tableModelMTree.dropTable( - getQualifiedDatabasePartialPath(plan.getDatabase()), plan.getTableName())); + () -> { + tableModelMTree.dropTable( + getQualifiedDatabasePartialPath(plan.getDatabase()), plan.getTableName()); + if (plan.getType() == ConfigPhysicalPlanType.CommitDeleteView) { + configSchemaStatistics.decreaseTreeViewTableNum(plan.getDatabase()); + } else { + configSchemaStatistics.decreaseBaseTableNum(plan.getDatabase()); + } + }); } public TSStatus renameTable(final RenameTablePlan plan) { @@ -1530,6 +1568,10 @@ public TSStatus commitDeleteColumn(final CommitDeleteColumnPlan plan) { plan.getColumnName())); } + public ConfigSchemaStatistics getConfigSchemaStatistics() { + return configSchemaStatistics; + } + // endregion @TestOnly diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java index 36c4ccc2f05e5..2850c93b1e736 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java @@ -1090,7 +1090,8 @@ private void serializeTableNode(final ConfigTableNode tableNode, final OutputStr } } - public void deserialize(final InputStream inputStream) throws IOException { + public void deserialize(final InputStream inputStream, final ConfigSchemaStatistics statistics) + throws IOException { byte type = ReadWriteIOUtils.readByte(inputStream); String name; @@ -1098,11 +1099,16 @@ public void deserialize(final InputStream inputStream) throws IOException { final Stack> stack = new Stack<>(); IConfigMNode databaseMNode; IConfigMNode internalMNode; - IConfigMNode tableNode; + ConfigTableNode tableNode; if (type == DATABASE_MNODE_TYPE) { databaseMNode = deserializeDatabaseMNode(inputStream); name = databaseMNode.getName(); + if (isTableModel) { + statistics.increaseTableDatabaseNum(); + } else { + statistics.increaseTreeDatabaseNum(); + } stack.push(new Pair<>(databaseMNode, true)); } else if (type == TABLE_MNODE_TYPE) { tableNode = deserializeTableMNode(inputStream); @@ -1133,15 +1139,28 @@ public void deserialize(final InputStream inputStream) throws IOException { name = internalMNode.getName(); break; case DATABASE_MNODE_TYPE: - databaseMNode = deserializeDatabaseMNode(inputStream).getAsMNode(); + databaseMNode = deserializeDatabaseMNode(inputStream); while (!stack.isEmpty() && Boolean.FALSE.equals(stack.peek().right)) { - databaseMNode.addChild(stack.pop().left); + final IConfigMNode node = stack.pop().left; + databaseMNode.addChild(node); + if (node instanceof ConfigTableNode) { + if (TreeViewSchema.isTreeViewTable(((ConfigTableNode) node).getTable())) { + statistics.increaseTreeViewTableNum(databaseMNode.getName()); + } else { + statistics.increaseBaseTableNum(databaseMNode.getName()); + } + } + } + if (isTableModel) { + statistics.increaseTableDatabaseNum(); + } else { + statistics.increaseTreeDatabaseNum(); } stack.push(new Pair<>(databaseMNode, true)); name = databaseMNode.getName(); break; case TABLE_MNODE_TYPE: - tableNode = deserializeTableMNode(inputStream).getAsMNode(); + tableNode = deserializeTableMNode(inputStream); stack.push(new Pair<>(tableNode, false)); name = tableNode.getName(); break; diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigSchemaStatistics.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigSchemaStatistics.java new file mode 100644 index 0000000000000..c4a9f33b39f0b --- /dev/null +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigSchemaStatistics.java @@ -0,0 +1,97 @@ +/* + * 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.confignode.persistence.schema; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicLong; + +/** + * The {@link ConfigSchemaStatistics} is used to: + * + *

1. Serve the {@link org.apache.iotdb.confignode.manager.partition.PartitionMetrics} for schema + * related metrics, to prevent too much scanning and lock acquisition, and to simplify the metric + * getter logic. + * + *

2. Be reserved for potential mem-control and quota functionalities expansion. + * + *

3. Be in consistency with SchemaRegionMemMetric in dataNode. + */ +public class ConfigSchemaStatistics { + public AtomicLong treeDatabaseNum = new AtomicLong(0); + + // Add 1 for information_schema + public AtomicLong tableDatabaseNum = new AtomicLong(1); + + public ConcurrentMap treeViewTableNum = new ConcurrentHashMap<>(); + public ConcurrentMap baseTableNum = new ConcurrentHashMap<>(); + + // Getter + + public long getTreeDatabaseNum() { + return treeDatabaseNum.get(); + } + + public long getTableDatabaseNum() { + return tableDatabaseNum.get(); + } + + public long getTreeViewTableNum(final String database) { + return treeViewTableNum.getOrDefault(database, 0L); + } + + public long getBaseTableNum(final String database) { + return baseTableNum.getOrDefault(database, 0L); + } + + // Setter + + public void increaseTreeDatabaseNum() { + treeDatabaseNum.incrementAndGet(); + } + + public void decreaseTreeDatabaseNum() { + treeDatabaseNum.decrementAndGet(); + } + + public void increaseTableDatabaseNum() { + tableDatabaseNum.incrementAndGet(); + } + + public void decreaseTableDatabaseNum() { + tableDatabaseNum.decrementAndGet(); + } + + public void increaseTreeViewTableNum(final String database) { + treeViewTableNum.compute(database, (db, num) -> num == null ? 1 : num + 1); + } + + public void decreaseTreeViewTableNum(final String database) { + treeViewTableNum.compute(database, (db, num) -> num != null && num > 1 ? num - 1 : null); + } + + public void increaseBaseTableNum(final String database) { + baseTableNum.compute(database, (db, num) -> num == null ? 1 : num + 1); + } + + public void decreaseBaseTableNum(final String database) { + baseTableNum.compute(database, (db, num) -> num != null && num > 1 ? num - 1 : null); + } +} diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java index 3ea3f2d06545d..5c0f1469d5ca6 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/schema/DeleteDatabaseProcedure.java @@ -201,6 +201,8 @@ protected Flow executeFromState(final ConfigNodeProcedureEnv env, final DeleteDa // Delete Database metrics PartitionMetrics.unbindDatabaseRelatedMetricsWhenUpdate( MetricService.getInstance(), deleteDatabaseSchema.getName()); + PartitionMetrics.unbindDatabaseTableMetrics( + MetricService.getInstance(), deleteDatabaseSchema.getName()); // Delete DatabasePartitionTable final TSStatus deleteConfigResult = diff --git a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java index 0e887886dcc46..750fb8b35c956 100644 --- a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java +++ b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java @@ -281,7 +281,7 @@ public void testSerialization() throws Exception { final ConfigMTree newTree = new ConfigMTree(false); final ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); - newTree.deserialize(inputStream); + newTree.deserialize(inputStream, new ConfigSchemaStatistics()); for (int i = 0; i < pathList.length; i++) { final TDatabaseSchema storageGroupSchema = @@ -357,7 +357,7 @@ public void testTableSerialization() throws Exception { final ConfigMTree newTree = new ConfigMTree(true); final ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); - newTree.deserialize(inputStream); + newTree.deserialize(inputStream, new ConfigSchemaStatistics()); for (int i = 0; i < pathList.length; i++) { final TDatabaseSchema storageGroupSchema = diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java index c2f9639de8e2c..73544fdfc2678 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java @@ -59,6 +59,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AddColumn; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AlterDB; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ClearCache; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateFunction; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateModel; @@ -414,6 +415,7 @@ private IQueryExecution createQueryExecutionForTableModel( queryContext.setStartTime(startTime); if (statement instanceof DropDB || statement instanceof ShowDB + || statement instanceof CountDB || statement instanceof CreateDB || statement instanceof AlterDB || statement instanceof Use diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java index 32b964ec584f1..3aaa38e85c8a5 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/TableConfigTaskVisitor.java @@ -80,6 +80,7 @@ import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.AlterTableRenameTableTask; import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.AlterTableSetPropertiesTask; import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ClearCacheTask; +import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CountDBTask; import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateDBTask; import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateTableTask; import org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.CreateTableViewTask; @@ -135,6 +136,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ClearCache; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ColumnDefinition; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateFunction; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateModel; @@ -398,6 +400,14 @@ protected IConfigTask visitShowDB(final ShowDB node, final MPPQueryContext conte canShowDB(accessControl, context.getSession().getUserName(), databaseName, context)); } + @Override + protected IConfigTask visitCountDB(final CountDB node, final MPPQueryContext context) { + context.setQueryType(QueryType.READ); + return new CountDBTask( + databaseName -> + canShowDB(accessControl, context.getSession().getUserName(), databaseName, context)); + } + public static boolean canShowDB( final AccessControl accessControl, final String userName, diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java index b617bac5f5461..e2eb6c1112704 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/ClusterConfigTaskExecutor.java @@ -3902,6 +3902,27 @@ public SettableFuture showDatabases( return future; } + @Override + public SettableFuture countDatabases(final Predicate canSeeDB) { + final SettableFuture future = SettableFuture.create(); + // Construct request using statement + final List databasePathPattern = Arrays.asList(ALL_RESULT_NODES); + try (final ConfigNodeClient client = + CONFIG_NODE_CLIENT_MANAGER.borrowClient(ConfigNodeInfo.CONFIG_REGION_ID)) { + // Send request to some API server + final TGetDatabaseReq req = + new TGetDatabaseReq(databasePathPattern, ALL_MATCH_SCOPE.serialize()) + .setIsTableModel(true); + final TShowDatabaseResp resp = client.showDatabase(req); + // build TSBlock, here we consider the information_schema + CountDatabaseTask.buildTSBlock( + (int) resp.getDatabaseInfoMap().keySet().stream().filter(canSeeDB).count() + 1, future); + } catch (final IOException | ClientManagerException | TException e) { + future.setException(e); + } + return future; + } + @Override public SettableFuture showCluster(final ShowCluster showCluster) { // As the implementation is identical, we'll simply translate to the diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java index 926fd37cf3ab3..0ceafc15b83a7 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/executor/IConfigTaskExecutor.java @@ -313,6 +313,8 @@ SettableFuture showThrottleQuota( SettableFuture showDatabases( final ShowDB showDB, final Predicate canSeenDB); + SettableFuture countDatabases(final Predicate canSeenDB); + SettableFuture showCluster(ShowCluster showCluster); SettableFuture useDatabase(final Use useDB, final IClientSession clientSession); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/CountDatabaseTask.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/CountDatabaseTask.java index cc856078afc88..720e2511dd032 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/CountDatabaseTask.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/config/metadata/CountDatabaseTask.java @@ -54,10 +54,10 @@ public static void buildTSBlock(int storageGroupNum, SettableFuture canSeenDB; + + public CountDBTask(final Predicate canSeenDB) { + this.canSeenDB = canSeenDB; + } + + @Override + public ListenableFuture execute(final IConfigTaskExecutor configTaskExecutor) + throws InterruptedException { + return configTaskExecutor.countDatabases(canSeenDB); + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java index 6a2b7eb34c165..bbb573b602740 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java @@ -68,6 +68,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CoalesceExpression; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Columns; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateIndex; @@ -431,6 +432,11 @@ protected Scope visitShowDB(ShowDB node, Optional context) { throw new SemanticException("Show Database statement is not supported yet."); } + @Override + protected Scope visitCountDB(CountDB node, Optional context) { + throw new SemanticException("Count Database statement is not supported yet."); + } + @Override protected Scope visitCreateTable(final CreateTable node, final Optional context) { validateProperties(node.getProperties(), context); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java index 84c8c9c002e29..dd45cdc148d12 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/metadata/fetcher/TableDeviceSchemaFetcher.java @@ -579,7 +579,7 @@ private void constructTableResults( mppQueryContext.reserveMemoryForFrontEnd(deviceEntry.ramBytesUsed()); deviceEntryList.add(deviceEntry); // Only cache those exact device query - // Fetch paths is null iff there are fuzzy queries related to id columns + // Fetch paths is null iff there are fuzzy queries related to tag columns if (Objects.nonNull(statement.getPartitionKeyList())) { cache.putAttributes(statement.getDatabase(), deviceID, attributeMap); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java index 5b43b467a3620..c899255de1b3d 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/AstVisitor.java @@ -357,6 +357,10 @@ protected R visitShowDB(final ShowDB node, final C context) { return visitStatement(node, context); } + protected R visitCountDB(final CountDB node, final C context) { + return visitStatement(node, context); + } + protected R visitCreateTable(final CreateTable node, final C context) { return visitStatement(node, context); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CountDB.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CountDB.java new file mode 100644 index 0000000000000..1935144d3f101 --- /dev/null +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/CountDB.java @@ -0,0 +1,61 @@ +/* + * 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.queryengine.plan.relational.sql.ast; + +import com.google.common.collect.ImmutableList; + +import java.util.List; + +import static java.util.Objects.requireNonNull; + +public class CountDB extends Statement { + + public CountDB(final NodeLocation location) { + super(requireNonNull(location, "location is null")); + } + + @Override + public R accept(final AstVisitor visitor, final C context) { + return visitor.visitCountDB(this, context); + } + + @Override + public List getChildren() { + return ImmutableList.of(); + } + + @Override + public int hashCode() { + return getClass().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + return (obj != null) && (getClass() == obj.getClass()); + } + + @Override + public String toString() { + return "COUNT DATABASES"; + } +} diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java index 76107bfa30e7b..100b43b94fdac 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/parser/AstBuilder.java @@ -54,6 +54,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ColumnDefinition; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Columns; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDevice; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountStatement; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB; @@ -391,6 +392,12 @@ public Node visitShowDatabasesStatement( return new ShowDB(getLocation(ctx), Objects.nonNull(ctx.DETAILS())); } + @Override + public Node visitCountDatabasesStatement( + final RelationalSqlParser.CountDatabasesStatementContext ctx) { + return new CountDB(getLocation(ctx)); + } + @Override public Node visitCreateDbStatement(final RelationalSqlParser.CreateDbStatementContext ctx) { List properties = ImmutableList.of(); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/SqlFormatter.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/SqlFormatter.java index e428b6cb78321..96ce1df26d71e 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/SqlFormatter.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/util/SqlFormatter.java @@ -26,6 +26,7 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AlterPipe; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ColumnDefinition; +import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CountDB; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateDB; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreateFunction; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.CreatePipe; @@ -663,6 +664,13 @@ protected Void visitShowDB(ShowDB node, Integer indent) { return null; } + @Override + protected Void visitCountDB(final CountDB node, final Integer context) { + builder.append("COUNT DATABASE"); + + return null; + } + @Override protected Void visitShowTables(final ShowTables node, final Integer indent) { builder.append("SHOW TABLES"); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/SchemaEngine.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/SchemaEngine.java index 3f59f9edf68ed..207af85f8f4a1 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/SchemaEngine.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/SchemaEngine.java @@ -32,6 +32,7 @@ import org.apache.iotdb.db.conf.IoTDBConfig; import org.apache.iotdb.db.conf.IoTDBDescriptor; import org.apache.iotdb.db.consensus.SchemaRegionConsensusImpl; +import org.apache.iotdb.db.schemaengine.metric.ISchemaEngineMetric; import org.apache.iotdb.db.schemaengine.metric.ISchemaRegionMetric; import org.apache.iotdb.db.schemaengine.metric.SchemaMetricManager; import org.apache.iotdb.db.schemaengine.rescon.CachedSchemaEngineStatistics; @@ -445,6 +446,10 @@ public ISchemaEngineStatistics getSchemaEngineStatistics() { return schemaEngineStatistics; } + public ISchemaEngineMetric getSchemaEngineMetric() { + return schemaMetricManager.getEngineMetric(); + } + public ISchemaRegionMetric getSchemaRegionMetric(int schemaRegionId) { return schemaMetricManager.getSchemaRegionMetric(schemaRegionId); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaEngineMemMetric.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaEngineMemMetric.java index 839477b434d17..3f271fb248a43 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaEngineMemMetric.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaEngineMemMetric.java @@ -38,17 +38,21 @@ public class SchemaEngineMemMetric implements ISchemaEngineMetric { private static final String MEM_CAPACITY = "schema_region_mem_capacity"; private static final String REGION_NUMBER = "schema_region_number"; private static final String DEVICE_NUMBER = "schema_region_total_device_cnt"; + private static final String TABLE_DEVICE_NUMBER = "schema_region_total_table_device_cnt"; private static final String SCHEMA_CONSENSUS = "schema_region_consensus"; private static final String SCHEMA_ENGINE_MODE = "schema_engine_mode"; + public static final String TABLE = "table"; private final MemSchemaEngineStatistics engineStatistics; + private AbstractMetricService metricService; - public SchemaEngineMemMetric(MemSchemaEngineStatistics engineStatistics) { + public SchemaEngineMemMetric(final MemSchemaEngineStatistics engineStatistics) { this.engineStatistics = engineStatistics; } @Override - public void bindTo(AbstractMetricService metricService) { + public void bindTo(final AbstractMetricService metricService) { + this.metricService = metricService; metricService.createAutoGauge( Metric.SCHEMA_ENGINE.toString(), MetricLevel.IMPORTANT, @@ -99,8 +103,20 @@ public void bindTo(AbstractMetricService metricService) { SCHEMA_CONSENSUS); } + public void bindTableMetrics(final String tableName) { + metricService.createAutoGauge( + Metric.SCHEMA_ENGINE.toString(), + MetricLevel.IMPORTANT, + engineStatistics, + statistics -> statistics.getTableDeviceNumber(tableName), + Tag.NAME.toString(), + TABLE_DEVICE_NUMBER, + TABLE, + tableName); + } + @Override - public void unbindFrom(AbstractMetricService metricService) { + public void unbindFrom(final AbstractMetricService metricService) { metricService.remove( MetricType.AUTO_GAUGE, Metric.SCHEMA_ENGINE.toString(), Tag.NAME.toString(), DEVICE_NUMBER); metricService.remove( @@ -123,6 +139,16 @@ public void unbindFrom(AbstractMetricService metricService) { MetricType.GAUGE, Metric.SCHEMA_ENGINE.toString(), Tag.NAME.toString(), SCHEMA_CONSENSUS); } + public void unbindTableMetrics(final String tableName) { + metricService.remove( + MetricType.AUTO_GAUGE, + Metric.SCHEMA_ENGINE.toString(), + Tag.NAME.toString(), + TABLE_DEVICE_NUMBER, + TABLE, + tableName); + } + /** * Encode SchemaRegionConsensusProtocol to ordinal. * diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaMetricManager.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaMetricManager.java index 85791e7366df8..ed1d57f59981f 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaMetricManager.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaMetricManager.java @@ -44,6 +44,10 @@ public SchemaMetricManager(ISchemaEngineStatistics engineStatistics) { MetricService.getInstance().addMetricSet(engineMetric); } + public ISchemaEngineMetric getEngineMetric() { + return engineMetric; + } + public void addSchemaRegionMetric(int schemaRegionId, ISchemaRegionMetric schemaRegionMetric) { schemaRegionMetricMap.put(schemaRegionId, schemaRegionMetric); MetricService.getInstance().addMetricSet(schemaRegionMetric); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaRegionMemMetric.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaRegionMemMetric.java index ae255cc0caa1e..5f481eb0294f2 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaRegionMemMetric.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/metric/SchemaRegionMemMetric.java @@ -34,10 +34,13 @@ public class SchemaRegionMemMetric implements ISchemaRegionMetric { private static final String MEM_USAGE = "schema_region_mem_usage"; private static final String SERIES_CNT = "schema_region_series_cnt"; + private static final String NON_VIEW_SERIES_CNT = "schema_region_non_view_series_cnt"; private static final String DEVICE_NUMBER = "schema_region_device_cnt"; + private static final String TABLE_DEVICE_NUMBER = "schema_region_table_device_cnt"; private static final String TEMPLATE_CNT = "activated_template_cnt"; private static final String TEMPLATE_SERIES_CNT = "template_series_cnt"; private static final String TRAVERSER_TIMER = "schema_region_traverser_timer"; + private AbstractMetricService metricService; private Timer traverserTimer = DoNothingMetricManager.DO_NOTHING_TIMER; @@ -53,6 +56,7 @@ public SchemaRegionMemMetric(MemSchemaRegionStatistics regionStatistics, String @Override public void bindTo(AbstractMetricService metricService) { + this.metricService = metricService; metricService.createAutoGauge( Metric.SCHEMA_REGION.toString(), MetricLevel.IMPORTANT, @@ -86,6 +90,17 @@ public void bindTo(AbstractMetricService metricService) { regionTagValue, Tag.DATABASE.toString(), database); + metricService.createAutoGauge( + Metric.SCHEMA_REGION.toString(), + MetricLevel.IMPORTANT, + regionStatistics, + i -> i.getSeriesNumber(false), + Tag.NAME.toString(), + NON_VIEW_SERIES_CNT, + Tag.REGION.toString(), + regionTagValue, + Tag.DATABASE.toString(), + database); metricService.createAutoGauge( Metric.SCHEMA_REGION.toString(), MetricLevel.IMPORTANT, @@ -120,6 +135,20 @@ public void bindTo(AbstractMetricService metricService) { database); } + public void bindTableMetrics(final String tableName) { + metricService.createAutoGauge( + Metric.SCHEMA_ENGINE.toString(), + MetricLevel.IMPORTANT, + regionStatistics, + statistics -> statistics.getTableDevicesNumber(tableName), + Tag.NAME.toString(), + TABLE_DEVICE_NUMBER, + Tag.REGION.toString(), + regionTagValue, + SchemaEngineMemMetric.TABLE, + tableName); + } + @Override public void unbindFrom(AbstractMetricService metricService) { traverserTimer = DoNothingMetricManager.DO_NOTHING_TIMER; @@ -150,6 +179,15 @@ public void unbindFrom(AbstractMetricService metricService) { regionTagValue, Tag.DATABASE.toString(), database); + metricService.remove( + MetricType.AUTO_GAUGE, + Metric.SCHEMA_REGION.toString(), + Tag.NAME.toString(), + NON_VIEW_SERIES_CNT, + Tag.REGION.toString(), + regionTagValue, + Tag.DATABASE.toString(), + database); metricService.remove( MetricType.AUTO_GAUGE, Metric.SCHEMA_REGION.toString(), @@ -179,6 +217,18 @@ public void unbindFrom(AbstractMetricService metricService) { database); } + public void unbindTableMetrics(final String tableName) { + metricService.remove( + MetricType.AUTO_GAUGE, + Metric.SCHEMA_ENGINE.toString(), + Tag.NAME.toString(), + TABLE_DEVICE_NUMBER, + Tag.REGION.toString(), + regionTagValue, + SchemaEngineMemMetric.TABLE, + tableName); + } + public void recordTraverser(long time) { traverserTimer.update(time, TimeUnit.MILLISECONDS); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/ISchemaEngineStatistics.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/ISchemaEngineStatistics.java index cca3cecfc6926..2389d4f282951 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/ISchemaEngineStatistics.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/ISchemaEngineStatistics.java @@ -33,6 +33,8 @@ public interface ISchemaEngineStatistics { long getTotalDevicesNumber(); + long getTableDeviceNumber(final String tableName); + int getSchemaRegionNumber(); long getTemplateSeriesNumber(); diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/MemSchemaEngineStatistics.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/MemSchemaEngineStatistics.java index c50dd62ecea5c..7deee2ccf24ca 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/MemSchemaEngineStatistics.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/MemSchemaEngineStatistics.java @@ -23,13 +23,19 @@ import org.apache.iotdb.commons.memory.MemoryBlockType; import org.apache.iotdb.db.conf.IoTDBDescriptor; import org.apache.iotdb.db.schemaengine.SchemaEngine; +import org.apache.iotdb.db.schemaengine.metric.ISchemaEngineMetric; +import org.apache.iotdb.db.schemaengine.metric.SchemaEngineMemMetric; import org.apache.iotdb.db.schemaengine.template.ClusterTemplateManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nonnull; + import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicLong; /** This class is used to record the global statistics of SchemaEngine in Memory mode. */ @@ -48,6 +54,7 @@ public class MemSchemaEngineStatistics implements ISchemaEngineStatistics { private final AtomicLong totalMeasurementNumber = new AtomicLong(0); private final AtomicLong totalViewNumber = new AtomicLong(0); private final AtomicLong totalDeviceNumber = new AtomicLong(0); + private final ConcurrentMap tableDeviceNumber = new ConcurrentHashMap<>(); private final Map templateUsage = new ConcurrentHashMap<>(); private volatile boolean allowToCreateNewSeries = true; @@ -129,6 +136,11 @@ public long getTotalDevicesNumber() { return totalDeviceNumber.get(); } + @Override + public long getTableDeviceNumber(final String tableName) { + return tableDeviceNumber.getOrDefault(tableName, 0L); + } + @Override public int getSchemaRegionNumber() { return SchemaEngine.getInstance().getSchemaRegionNumber(); @@ -186,6 +198,38 @@ public void deleteDevice(long cnt) { totalDeviceNumber.addAndGet(-cnt); } + public void addTableDevice(final String table) { + tableDeviceNumber.compute( + table, + (tableName, num) -> { + if (Objects.nonNull(num)) { + return num + 1; + } + final ISchemaEngineMetric metric = SchemaEngine.getInstance().getSchemaEngineMetric(); + if (metric instanceof SchemaEngineMemMetric) { + ((SchemaEngineMemMetric) metric).bindTableMetrics(table); + } + return 1L; + }); + } + + public void decreaseTableDevice(final String table, final long decrease) { + tableDeviceNumber.computeIfPresent(table, (tableName, num) -> num - decrease); + } + + // Reset table device, will alter the schema statistics as well + public void resetTableDevice(final @Nonnull String table) { + final Long num = tableDeviceNumber.remove(table); + if (Objects.isNull(num)) { + return; + } + totalDeviceNumber.addAndGet(-num); + final ISchemaEngineMetric metric = SchemaEngine.getInstance().getSchemaEngineMetric(); + if (metric instanceof SchemaEngineMemMetric) { + ((SchemaEngineMemMetric) metric).unbindTableMetrics(table); + } + } + @Override public MemSchemaEngineStatistics getAsMemSchemaEngineStatistics() { return this; diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/MemSchemaRegionStatistics.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/MemSchemaRegionStatistics.java index bd79953ee6957..36bbabdff81ba 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/MemSchemaRegionStatistics.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/rescon/MemSchemaRegionStatistics.java @@ -19,6 +19,9 @@ package org.apache.iotdb.db.schemaengine.rescon; +import org.apache.iotdb.db.schemaengine.SchemaEngine; +import org.apache.iotdb.db.schemaengine.metric.ISchemaRegionMetric; +import org.apache.iotdb.db.schemaengine.metric.SchemaRegionMemMetric; import org.apache.iotdb.db.schemaengine.template.ClusterTemplateManager; import org.apache.iotdb.db.schemaengine.template.Template; @@ -126,18 +129,37 @@ public void decreaseTableAttributeMemory(final String table, final long num) { } public void addTableDevice(final String table) { - tableDeviceNumber.compute(table, (tableName, num) -> Objects.nonNull(num) ? num + 1 : 1L); + tableDeviceNumber.compute( + table, + (tableName, num) -> { + if (Objects.nonNull(num)) { + return num + 1; + } + final ISchemaRegionMetric metric = + SchemaEngine.getInstance().getSchemaRegionMetric(schemaRegionId); + if (metric instanceof SchemaRegionMemMetric) { + ((SchemaRegionMemMetric) metric).bindTableMetrics(table); + } + return 1L; + }); + schemaEngineStatistics.addTableDevice(table); } public void decreaseTableDevice(final String table, final long decrease) { tableDeviceNumber.computeIfPresent(table, (tableName, num) -> num - decrease); + schemaEngineStatistics.decreaseTableDevice(table, decrease); } // Reset table device, will alter the schema statistics as well public void resetTableDevice(final String table) { final long num = tableDeviceNumber.remove(table); devicesNumber.addAndGet(-num); - schemaEngineStatistics.deleteDevice(num); + final ISchemaRegionMetric metric = + SchemaEngine.getInstance().getSchemaRegionMetric(schemaRegionId); + if (metric instanceof SchemaRegionMemMetric) { + ((SchemaRegionMemMetric) metric).unbindTableMetrics(table); + } + schemaEngineStatistics.resetTableDevice(table); } public void addDevice() { diff --git a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Metric.java b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Metric.java index ad14e90cd57de..b94d336b132df 100644 --- a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Metric.java +++ b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Metric.java @@ -30,6 +30,8 @@ public enum Metric { // cluster related NODE_NUM("node_num"), DATABASE_NUM("database_num"), + TABLE_DATABASE_NUM("table_database_num"), + TABLE_NUM("table_num"), REGION_NUM("region_num"), REGION_NUM_IN_DATA_NODE("region_num_in_data_node"), REGION_GROUP_LEADER_NUM_IN_DATA_NODE("region_group_leader_num_in_data_node"), diff --git a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4 b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4 index 7357196219f51..f94bf13253c7e 100644 --- a/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4 +++ b/iotdb-core/relational-grammar/src/main/antlr4/org/apache/iotdb/db/relational/grammar/sql/RelationalSql.g4 @@ -49,6 +49,7 @@ statement // Database Statement | useDatabaseStatement | showDatabasesStatement + | countDatabasesStatement | createDbStatement | alterDbStatement | dropDbStatement @@ -186,6 +187,10 @@ showDatabasesStatement : SHOW DATABASES (DETAILS)? ; +countDatabasesStatement + : COUNT DATABASES + ; + createDbStatement : CREATE DATABASE (IF NOT EXISTS)? database=identifier (WITH properties)? ;