You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by hu...@apache.org on 2022/12/18 15:58:44 UTC
[iotdb] 01/05: add metrics: query_plan_cost
This is an automated email from the ASF dual-hosted git repository.
hui pushed a commit to branch lmh/addQueryMetrics
in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 08d478707b464b43627a889be9f7bf6bc19e9f72
Author: Minghui Liu <li...@foxmail.com>
AuthorDate: Thu Dec 15 10:43:47 2022 +0800
add metrics: query_plan_cost
---
.../apache/iotdb/metrics/config/MetricConfig.java | 4 +-
.../iotdb/commons/service/metric/enums/Metric.java | 3 +-
.../iotdb/commons/service/metric/enums/Tag.java | 3 +-
.../iotdb/db/engine/cache/ChunkCacheMetrics.java | 3 +-
.../cache/TimeSeriesMetadataCacheMetrics.java | 2 +-
.../iotdb/db/mpp/metric/QueryMetricsManager.java | 49 +++++++++
.../metric/QueryPlanCostMetrics.java} | 58 +++++------
.../iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java | 114 +++++++++------------
.../apache/iotdb/db/mpp/plan/analyze/Analyzer.java | 11 +-
.../db/mpp/plan/execution/QueryExecution.java | 8 ++
.../db/mpp/plan/parser/StatementGenerator.java | 88 ++++++++--------
.../iotdb/db/mpp/plan/planner/LogicalPlanner.java | 9 +-
.../db/service/metrics/DataNodeMetricsHelper.java | 4 +
13 files changed, 214 insertions(+), 142 deletions(-)
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java
index a2558f8b9b..b17410e12d 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java
@@ -34,10 +34,10 @@ public class MetricConfig {
private MetricFrameType metricFrameType = MetricFrameType.MICROMETER;
/** The list of reporters provide metrics for external tool */
- private List<ReporterType> metricReporterList = Collections.emptyList();
+ private List<ReporterType> metricReporterList = Collections.singletonList(ReporterType.JMX);
/** The level of metric service */
- private MetricLevel metricLevel = MetricLevel.CORE;
+ private MetricLevel metricLevel = MetricLevel.IMPORTANT;
/** The period of async collection of some metrics in second */
private Integer asyncCollectPeriodInSecond = 5;
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Metric.java b/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Metric.java
index fc534ef595..cc9b017328 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Metric.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Metric.java
@@ -61,7 +61,8 @@ public enum Metric {
THRIFT_CONNECTIONS,
THRIFT_ACTIVE_THREADS,
IOT_CONSENSUS,
- STAGE;
+ STAGE,
+ QUERY_PLAN_COST;
@Override
public String toString() {
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Tag.java b/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Tag.java
index 1b02b0161c..65280a22a2 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Tag.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/service/metric/enums/Tag.java
@@ -23,7 +23,8 @@ public enum Tag {
TYPE,
NAME,
REGION,
- STATUS;
+ STATUS,
+ STAGE;
@Override
public String toString() {
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCacheMetrics.java b/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCacheMetrics.java
index 58903a6191..5b092a3930 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCacheMetrics.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCacheMetrics.java
@@ -29,7 +29,8 @@ import org.apache.iotdb.metrics.utils.MetricType;
import java.util.Objects;
public class ChunkCacheMetrics implements IMetricSet {
- private ChunkCache chunkCache;
+
+ private final ChunkCache chunkCache;
public ChunkCacheMetrics(ChunkCache chunkCache) {
this.chunkCache = chunkCache;
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCacheMetrics.java b/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCacheMetrics.java
index 84684f624c..d0a5e66008 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCacheMetrics.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCacheMetrics.java
@@ -30,7 +30,7 @@ import java.util.Objects;
public class TimeSeriesMetadataCacheMetrics implements IMetricSet {
- private TimeSeriesMetadataCache timeSeriesMetadataCache;
+ private final TimeSeriesMetadataCache timeSeriesMetadataCache;
public TimeSeriesMetadataCacheMetrics(TimeSeriesMetadataCache timeSeriesMetadataCache) {
this.timeSeriesMetadataCache = timeSeriesMetadataCache;
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/metric/QueryMetricsManager.java b/server/src/main/java/org/apache/iotdb/db/mpp/metric/QueryMetricsManager.java
new file mode 100644
index 0000000000..8a4e878733
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/metric/QueryMetricsManager.java
@@ -0,0 +1,49 @@
+/*
+ * 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.mpp.metric;
+
+import org.apache.iotdb.commons.service.metric.MetricService;
+import org.apache.iotdb.commons.service.metric.enums.Metric;
+import org.apache.iotdb.commons.service.metric.enums.Tag;
+import org.apache.iotdb.metrics.type.Timer;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+
+public class QueryMetricsManager {
+
+ private final MetricService metricService = MetricService.getInstance();
+
+ public void addPlanCost(String stage, long costTimeInNanos) {
+ Timer timer =
+ metricService.getOrCreateTimer(
+ Metric.QUERY_PLAN_COST.toString(), MetricLevel.IMPORTANT, Tag.STAGE.toString(), stage);
+ timer.updateNanos(costTimeInNanos);
+ }
+
+ public static QueryMetricsManager getInstance() {
+ return QueryMetricsManager.QueryMetricsManagerHolder.INSTANCE;
+ }
+
+ private static class QueryMetricsManagerHolder {
+
+ private static final QueryMetricsManager INSTANCE = new QueryMetricsManager();
+
+ private QueryMetricsManagerHolder() {}
+ }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCacheMetrics.java b/server/src/main/java/org/apache/iotdb/db/mpp/metric/QueryPlanCostMetrics.java
similarity index 54%
copy from server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCacheMetrics.java
copy to server/src/main/java/org/apache/iotdb/db/mpp/metric/QueryPlanCostMetrics.java
index 58903a6191..122ba3ea23 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCacheMetrics.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/metric/QueryPlanCostMetrics.java
@@ -17,7 +17,7 @@
* under the License.
*/
-package org.apache.iotdb.db.engine.cache;
+package org.apache.iotdb.db.mpp.metric;
import org.apache.iotdb.commons.service.metric.enums.Metric;
import org.apache.iotdb.commons.service.metric.enums.Tag;
@@ -26,42 +26,42 @@ import org.apache.iotdb.metrics.metricsets.IMetricSet;
import org.apache.iotdb.metrics.utils.MetricLevel;
import org.apache.iotdb.metrics.utils.MetricType;
-import java.util.Objects;
+import java.util.Arrays;
+import java.util.List;
-public class ChunkCacheMetrics implements IMetricSet {
- private ChunkCache chunkCache;
+public class QueryPlanCostMetrics implements IMetricSet {
- public ChunkCacheMetrics(ChunkCache chunkCache) {
- this.chunkCache = chunkCache;
- }
+ public static final String SQL_PARSER = "sql_parser";
+ public static final String ANALYZER = "analyzer";
+ public static final String LOGICAL_PLANNER = "logical_planner";
+ public static final String DISTRIBUTION_PLANNER = "distribution_planner";
- @Override
- public void bindTo(AbstractMetricService metricService) {
- metricService.createAutoGauge(
- Metric.CACHE_HIT.toString(),
- MetricLevel.IMPORTANT,
- chunkCache,
- o -> (long) o.getHitRate(),
- Tag.NAME.toString(),
- "chunk");
- }
+ public static final String PARTITION_FETCHER = "partition_fetcher";
+ public static final String SCHEMA_FETCHER = "schema_fetcher";
- @Override
- public void unbindFrom(AbstractMetricService metricService) {
- metricService.remove(
- MetricType.AUTO_GAUGE, Metric.CACHE_HIT.toString(), Tag.NAME.toString(), "chunk");
- }
+ private final String metric = Metric.QUERY_PLAN_COST.toString();
+ private final String tagKey = Tag.STAGE.toString();
+
+ private static final List<String> stages =
+ Arrays.asList(
+ SQL_PARSER,
+ ANALYZER,
+ LOGICAL_PLANNER,
+ DISTRIBUTION_PLANNER,
+ PARTITION_FETCHER,
+ SCHEMA_FETCHER);
@Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- ChunkCacheMetrics that = (ChunkCacheMetrics) o;
- return Objects.equals(chunkCache, that.chunkCache);
+ public void bindTo(AbstractMetricService metricService) {
+ for (String stage : stages) {
+ metricService.getOrCreateTimer(metric, MetricLevel.IMPORTANT, tagKey, stage);
+ }
}
@Override
- public int hashCode() {
- return Objects.hash(chunkCache);
+ public void unbindFrom(AbstractMetricService metricService) {
+ for (String stage : stages) {
+ metricService.remove(MetricType.TIMER, metric, tagKey, stage);
+ }
}
}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
index 81910ef650..8b582fb05a 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/AnalyzeVisitor.java
@@ -46,6 +46,7 @@ import org.apache.iotdb.db.mpp.common.header.DatasetHeader;
import org.apache.iotdb.db.mpp.common.header.DatasetHeaderFactory;
import org.apache.iotdb.db.mpp.common.schematree.DeviceSchemaInfo;
import org.apache.iotdb.db.mpp.common.schematree.ISchemaTree;
+import org.apache.iotdb.db.mpp.metric.QueryMetricsManager;
import org.apache.iotdb.db.mpp.plan.Coordinator;
import org.apache.iotdb.db.mpp.plan.execution.ExecutionResult;
import org.apache.iotdb.db.mpp.plan.expression.Expression;
@@ -153,6 +154,8 @@ import static org.apache.iotdb.commons.conf.IoTDBConstant.LOSS;
import static org.apache.iotdb.commons.conf.IoTDBConstant.ONE_LEVEL_PATH_WILDCARD;
import static org.apache.iotdb.db.metadata.MetadataConstant.ALL_RESULT_NODES;
import static org.apache.iotdb.db.mpp.common.header.ColumnHeaderConstant.DEVICE;
+import static org.apache.iotdb.db.mpp.metric.QueryPlanCostMetrics.PARTITION_FETCHER;
+import static org.apache.iotdb.db.mpp.metric.QueryPlanCostMetrics.SCHEMA_FETCHER;
import static org.apache.iotdb.db.mpp.plan.analyze.SelectIntoUtils.constructTargetDevice;
import static org.apache.iotdb.db.mpp.plan.analyze.SelectIntoUtils.constructTargetMeasurement;
import static org.apache.iotdb.db.mpp.plan.analyze.SelectIntoUtils.constructTargetPath;
@@ -201,13 +204,16 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
// request schema fetch API
logger.debug("[StartFetchSchema]");
+ long startTime = System.nanoTime();
ISchemaTree schemaTree;
if (queryStatement.isGroupByTag()) {
schemaTree = schemaFetcher.fetchSchemaWithTags(patternTree);
} else {
schemaTree = schemaFetcher.fetchSchema(patternTree);
}
+ QueryMetricsManager.getInstance().addPlanCost(SCHEMA_FETCHER, System.nanoTime() - startTime);
logger.debug("[EndFetchSchema]");
+
// If there is no leaf node in the schema tree, the query should be completed immediately
if (schemaTree.isEmpty()) {
if (queryStatement.isSelectInto()) {
@@ -228,8 +234,23 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
if (analysis.hasValueFilter()) {
throw new SemanticException("Only time filters are supported in LAST query");
}
+
analyzeOrderBy(analysis, queryStatement);
- return analyzeLast(analysis, schemaTree.getAllMeasurement(), schemaTree);
+
+ List<MeasurementPath> allSelectedPath = schemaTree.getAllMeasurement();
+ analyzeLastSource(analysis, allSelectedPath);
+
+ // set header
+ analysis.setRespDatasetHeader(DatasetHeaderFactory.getLastQueryHeader());
+
+ // fetch partition information
+ Set<String> deviceSet =
+ allSelectedPath.stream().map(MeasurementPath::getDevice).collect(Collectors.toSet());
+ DataPartition dataPartition =
+ fetchDataPartitionByDevices(deviceSet, schemaTree, analysis.getGlobalTimeFilter());
+ analysis.setDataPartitionInfo(dataPartition);
+
+ return analysis;
}
List<Pair<Expression, String>> outputExpressions;
@@ -328,8 +349,7 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
analysis.setHasValueFilter(hasValueFilter);
}
- private Analysis analyzeLast(
- Analysis analysis, List<MeasurementPath> allSelectedPath, ISchemaTree schemaTree) {
+ private void analyzeLastSource(Analysis analysis, List<MeasurementPath> allSelectedPath) {
Set<Expression> sourceExpressions;
List<SortItem> sortItemList = analysis.getMergeOrderParameter().getSortItemList();
if (sortItemList.size() > 0) {
@@ -352,47 +372,7 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
.map(TimeSeriesOperand::new)
.collect(Collectors.toCollection(LinkedHashSet::new));
}
-
analysis.setSourceExpressions(sourceExpressions);
-
- analysis.setRespDatasetHeader(DatasetHeaderFactory.getLastQueryHeader());
-
- Set<String> deviceSet =
- allSelectedPath.stream().map(MeasurementPath::getDevice).collect(Collectors.toSet());
-
- Pair<List<TTimePartitionSlot>, Pair<Boolean, Boolean>> res =
- getTimePartitionSlotList(analysis.getGlobalTimeFilter());
-
- DataPartition dataPartition;
-
- // there is no satisfied time range
- if (res.left.isEmpty() && !res.right.left) {
- dataPartition =
- new DataPartition(
- Collections.emptyMap(),
- CONFIG.getSeriesPartitionExecutorClass(),
- CONFIG.getSeriesPartitionSlotNum());
- } else {
- Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
- for (String devicePath : deviceSet) {
- DataPartitionQueryParam queryParam =
- new DataPartitionQueryParam(devicePath, res.left, res.right.left, res.right.right);
- sgNameToQueryParamsMap
- .computeIfAbsent(schemaTree.getBelongedDatabase(devicePath), key -> new ArrayList<>())
- .add(queryParam);
- }
-
- if (res.right.left || res.right.right) {
- dataPartition =
- partitionFetcher.getDataPartitionWithUnclosedTimeRange(sgNameToQueryParamsMap);
- } else {
- dataPartition = partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
- }
- }
-
- analysis.setDataPartitionInfo(dataPartition);
-
- return analysis;
}
private Map<Integer, List<Pair<Expression, String>>> analyzeSelect(
@@ -1168,28 +1148,34 @@ public class AnalyzeVisitor extends StatementVisitor<Analysis, MPPQueryContext>
private DataPartition fetchDataPartitionByDevices(
Set<String> deviceSet, ISchemaTree schemaTree, Filter globalTimeFilter) {
- Pair<List<TTimePartitionSlot>, Pair<Boolean, Boolean>> res =
- getTimePartitionSlotList(globalTimeFilter);
- // there is no satisfied time range
- if (res.left.isEmpty() && !res.right.left) {
- return new DataPartition(
- Collections.emptyMap(),
- CONFIG.getSeriesPartitionExecutorClass(),
- CONFIG.getSeriesPartitionSlotNum());
- }
- Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
- for (String devicePath : deviceSet) {
- DataPartitionQueryParam queryParam =
- new DataPartitionQueryParam(devicePath, res.left, res.right.left, res.right.right);
- sgNameToQueryParamsMap
- .computeIfAbsent(schemaTree.getBelongedDatabase(devicePath), key -> new ArrayList<>())
- .add(queryParam);
- }
+ long startTime = System.nanoTime();
+ try {
+ Pair<List<TTimePartitionSlot>, Pair<Boolean, Boolean>> res =
+ getTimePartitionSlotList(globalTimeFilter);
+ // there is no satisfied time range
+ if (res.left.isEmpty() && !res.right.left) {
+ return new DataPartition(
+ Collections.emptyMap(),
+ CONFIG.getSeriesPartitionExecutorClass(),
+ CONFIG.getSeriesPartitionSlotNum());
+ }
+ Map<String, List<DataPartitionQueryParam>> sgNameToQueryParamsMap = new HashMap<>();
+ for (String devicePath : deviceSet) {
+ DataPartitionQueryParam queryParam =
+ new DataPartitionQueryParam(devicePath, res.left, res.right.left, res.right.right);
+ sgNameToQueryParamsMap
+ .computeIfAbsent(schemaTree.getBelongedDatabase(devicePath), key -> new ArrayList<>())
+ .add(queryParam);
+ }
- if (res.right.left || res.right.right) {
- return partitionFetcher.getDataPartitionWithUnclosedTimeRange(sgNameToQueryParamsMap);
- } else {
- return partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
+ if (res.right.left || res.right.right) {
+ return partitionFetcher.getDataPartitionWithUnclosedTimeRange(sgNameToQueryParamsMap);
+ } else {
+ return partitionFetcher.getDataPartition(sgNameToQueryParamsMap);
+ }
+ } finally {
+ QueryMetricsManager.getInstance()
+ .addPlanCost(PARTITION_FETCHER, System.nanoTime() - startTime);
}
}
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
index 010b491e55..679a71627f 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/analyze/Analyzer.java
@@ -21,9 +21,11 @@ package org.apache.iotdb.db.mpp.plan.analyze;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.mpp.common.MPPQueryContext;
+import org.apache.iotdb.db.mpp.metric.QueryMetricsManager;
import org.apache.iotdb.db.mpp.plan.statement.Statement;
import static org.apache.iotdb.db.mpp.common.QueryId.mockQueryId;
+import static org.apache.iotdb.db.mpp.metric.QueryPlanCostMetrics.ANALYZER;
/** Analyze the statement and generate Analysis. */
public class Analyzer {
@@ -40,7 +42,14 @@ public class Analyzer {
}
public Analysis analyze(Statement statement) {
- return new AnalyzeVisitor(partitionFetcher, schemaFetcher).process(statement, context);
+ long startTime = System.nanoTime();
+ Analysis analysis =
+ new AnalyzeVisitor(partitionFetcher, schemaFetcher).process(statement, context);
+
+ if (statement.isQuery()) {
+ QueryMetricsManager.getInstance().addPlanCost(ANALYZER, System.nanoTime() - startTime);
+ }
+ return analysis;
}
public static void validate(Statement statement) {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/QueryExecution.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/QueryExecution.java
index 7cfa0a3fa1..c150183527 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/QueryExecution.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/execution/QueryExecution.java
@@ -33,6 +33,7 @@ import org.apache.iotdb.db.mpp.execution.QueryState;
import org.apache.iotdb.db.mpp.execution.QueryStateMachine;
import org.apache.iotdb.db.mpp.execution.exchange.ISourceHandle;
import org.apache.iotdb.db.mpp.execution.exchange.MPPDataExchangeService;
+import org.apache.iotdb.db.mpp.metric.QueryMetricsManager;
import org.apache.iotdb.db.mpp.plan.analyze.Analysis;
import org.apache.iotdb.db.mpp.plan.analyze.Analyzer;
import org.apache.iotdb.db.mpp.plan.analyze.IPartitionFetcher;
@@ -81,6 +82,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Throwables.throwIfUnchecked;
+import static org.apache.iotdb.db.mpp.metric.QueryPlanCostMetrics.DISTRIBUTION_PLANNER;
import static org.apache.iotdb.db.mpp.plan.constant.DataNodeEndPoints.isSameNode;
/**
@@ -300,8 +302,14 @@ public class QueryExecution implements IQueryExecution {
// Generate the distributed plan and split it into fragments
public void doDistributedPlan() {
+ long startTime = System.nanoTime();
DistributionPlanner planner = new DistributionPlanner(this.analysis, this.logicalPlan);
this.distributedPlan = planner.planFragments();
+
+ if (rawStatement.isQuery()) {
+ QueryMetricsManager.getInstance()
+ .addPlanCost(DISTRIBUTION_PLANNER, System.nanoTime() - startTime);
+ }
if (isQuery() && logger.isDebugEnabled()) {
logger.debug(
"distribution plan done. Fragment instance count is {}, details is: \n {}",
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/StatementGenerator.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/StatementGenerator.java
index 151a475d67..604442462e 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/StatementGenerator.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/parser/StatementGenerator.java
@@ -25,6 +25,7 @@ import org.apache.iotdb.commons.path.PartialPath;
import org.apache.iotdb.db.exception.query.QueryProcessException;
import org.apache.iotdb.db.metadata.template.TemplateQueryType;
import org.apache.iotdb.db.metadata.utils.MetaFormatUtils;
+import org.apache.iotdb.db.mpp.metric.QueryMetricsManager;
import org.apache.iotdb.db.mpp.plan.expression.binary.GreaterEqualExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.LessThanExpression;
import org.apache.iotdb.db.mpp.plan.expression.binary.LogicAndExpression;
@@ -101,6 +102,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import static org.apache.iotdb.db.mpp.metric.QueryPlanCostMetrics.SQL_PARSER;
+
/** Convert SQL and RPC requests to {@link Statement}. */
public class StatementGenerator {
@@ -472,48 +475,53 @@ public class StatementGenerator {
}
private static Statement invokeParser(String sql, ZoneId zoneId) {
- ASTVisitor astVisitor = new ASTVisitor();
- astVisitor.setZoneId(zoneId);
-
- CharStream charStream1 = CharStreams.fromString(sql);
-
- SqlLexer lexer1 = new SqlLexer(charStream1);
- lexer1.removeErrorListeners();
- lexer1.addErrorListener(SQLParseError.INSTANCE);
-
- CommonTokenStream tokens1 = new CommonTokenStream(lexer1);
-
- IoTDBSqlParser parser1 = new IoTDBSqlParser(tokens1);
- parser1.getInterpreter().setPredictionMode(PredictionMode.SLL);
- parser1.removeErrorListeners();
- parser1.addErrorListener(SQLParseError.INSTANCE);
-
- ParseTree tree;
+ long startTime = System.nanoTime();
try {
- // STAGE 1: try with simpler/faster SLL(*)
- tree = parser1.singleStatement();
- // if we get here, there was no syntax error and SLL(*) was enough;
- // there is no need to try full LL(*)
- } catch (Exception ex) {
- CharStream charStream2 = CharStreams.fromString(sql);
-
- SqlLexer lexer2 = new SqlLexer(charStream2);
- lexer2.removeErrorListeners();
- lexer2.addErrorListener(SQLParseError.INSTANCE);
-
- CommonTokenStream tokens2 = new CommonTokenStream(lexer2);
-
- org.apache.iotdb.db.qp.sql.IoTDBSqlParser parser2 =
- new org.apache.iotdb.db.qp.sql.IoTDBSqlParser(tokens2);
- parser2.getInterpreter().setPredictionMode(PredictionMode.LL);
- parser2.removeErrorListeners();
- parser2.addErrorListener(SQLParseError.INSTANCE);
-
- // STAGE 2: parser with full LL(*)
- tree = parser2.singleStatement();
- // if we get here, it's LL not SLL
+ ASTVisitor astVisitor = new ASTVisitor();
+ astVisitor.setZoneId(zoneId);
+
+ CharStream charStream1 = CharStreams.fromString(sql);
+
+ SqlLexer lexer1 = new SqlLexer(charStream1);
+ lexer1.removeErrorListeners();
+ lexer1.addErrorListener(SQLParseError.INSTANCE);
+
+ CommonTokenStream tokens1 = new CommonTokenStream(lexer1);
+
+ IoTDBSqlParser parser1 = new IoTDBSqlParser(tokens1);
+ parser1.getInterpreter().setPredictionMode(PredictionMode.SLL);
+ parser1.removeErrorListeners();
+ parser1.addErrorListener(SQLParseError.INSTANCE);
+
+ ParseTree tree;
+ try {
+ // STAGE 1: try with simpler/faster SLL(*)
+ tree = parser1.singleStatement();
+ // if we get here, there was no syntax error and SLL(*) was enough;
+ // there is no need to try full LL(*)
+ } catch (Exception ex) {
+ CharStream charStream2 = CharStreams.fromString(sql);
+
+ SqlLexer lexer2 = new SqlLexer(charStream2);
+ lexer2.removeErrorListeners();
+ lexer2.addErrorListener(SQLParseError.INSTANCE);
+
+ CommonTokenStream tokens2 = new CommonTokenStream(lexer2);
+
+ org.apache.iotdb.db.qp.sql.IoTDBSqlParser parser2 =
+ new org.apache.iotdb.db.qp.sql.IoTDBSqlParser(tokens2);
+ parser2.getInterpreter().setPredictionMode(PredictionMode.LL);
+ parser2.removeErrorListeners();
+ parser2.addErrorListener(SQLParseError.INSTANCE);
+
+ // STAGE 2: parser with full LL(*)
+ tree = parser2.singleStatement();
+ // if we get here, it's LL not SLL
+ }
+ return astVisitor.visit(tree);
+ } finally {
+ QueryMetricsManager.getInstance().addPlanCost(SQL_PARSER, System.nanoTime() - startTime);
}
- return astVisitor.visit(tree);
}
private static void addMeasurementAndValue(
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanner.java b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanner.java
index 308887f53a..cc25e475ac 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanner.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/plan/planner/LogicalPlanner.java
@@ -19,14 +19,16 @@
package org.apache.iotdb.db.mpp.plan.planner;
import org.apache.iotdb.db.mpp.common.MPPQueryContext;
+import org.apache.iotdb.db.mpp.metric.QueryMetricsManager;
import org.apache.iotdb.db.mpp.plan.analyze.Analysis;
import org.apache.iotdb.db.mpp.plan.optimization.PlanOptimizer;
import org.apache.iotdb.db.mpp.plan.planner.plan.LogicalQueryPlan;
import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNode;
-import org.apache.iotdb.db.mpp.plan.statement.crud.QueryStatement;
import java.util.List;
+import static org.apache.iotdb.db.mpp.metric.QueryPlanCostMetrics.LOGICAL_PLANNER;
+
/** Generate a logical plan for the statement. */
public class LogicalPlanner {
@@ -39,10 +41,13 @@ public class LogicalPlanner {
}
public LogicalQueryPlan plan(Analysis analysis) {
+ long startTime = System.nanoTime();
PlanNode rootNode = new LogicalPlanVisitor(analysis).process(analysis.getStatement(), context);
// optimize the query logical plan
- if (analysis.getStatement() instanceof QueryStatement) {
+ if (analysis.getStatement().isQuery()) {
+ QueryMetricsManager.getInstance().addPlanCost(LOGICAL_PLANNER, System.nanoTime() - startTime);
+
for (PlanOptimizer optimizer : optimizers) {
rootNode = optimizer.optimize(rootNode, context);
}
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/DataNodeMetricsHelper.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/DataNodeMetricsHelper.java
index e36b3b653e..be59c2b288 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/DataNodeMetricsHelper.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/DataNodeMetricsHelper.java
@@ -20,6 +20,7 @@
package org.apache.iotdb.db.service.metrics;
import org.apache.iotdb.commons.service.metric.MetricService;
+import org.apache.iotdb.db.mpp.metric.QueryPlanCostMetrics;
import org.apache.iotdb.metrics.metricsets.jvm.JvmMetrics;
import org.apache.iotdb.metrics.metricsets.logback.LogbackMetrics;
@@ -31,5 +32,8 @@ public class DataNodeMetricsHelper {
MetricService.getInstance().addMetricSet(new FileMetrics());
MetricService.getInstance().addMetricSet(new ProcessMetrics());
MetricService.getInstance().addMetricSet(new SystemMetrics(true));
+
+ // bind query related metrics
+ MetricService.getInstance().addMetricSet(new QueryPlanCostMetrics());
}
}