Skip to content

Commit 098306c

Browse files
authored
Optimize the implantation of EXPLAIN ANALYZE
1 parent 95d06f6 commit 098306c

File tree

17 files changed

+174
-65
lines changed

17 files changed

+174
-65
lines changed

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@
8282
import org.apache.iotdb.db.queryengine.execution.operator.source.relational.aggregation.grouped.StreamingHashAggregationOperator;
8383
import org.apache.iotdb.db.queryengine.execution.relational.ColumnTransformerBuilder;
8484
import org.apache.iotdb.db.queryengine.plan.analyze.TypeProvider;
85-
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.ExplainAnalyzeNode;
8685
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
8786
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
8887
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
@@ -110,6 +109,7 @@
110109
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.AggregationNode;
111110
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.AggregationTableScanNode;
112111
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.CollectNode;
112+
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.ExplainAnalyzeNode;
113113
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.FilterNode;
114114
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.GapFillNode;
115115
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.JoinNode;

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/distribution/ExchangeNodeAdder.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,10 @@ public PlanNode visitExplainAnalyze(ExplainAnalyzeNode node, NodeGroupContext co
421421
newNode.setChild(exchangeNode);
422422

423423
context.hasExchangeNode = true;
424+
context.putNodeDistribution(
425+
newNode.getPlanNodeId(),
426+
new NodeDistribution(
427+
NodeDistributionType.DIFFERENT_FROM_ALL_CHILDREN, DataPartition.NOT_ASSIGNED));
424428
return newNode;
425429
}
426430

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/ExplainAnalyzeNode.java

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@
2121

2222
import org.apache.iotdb.db.queryengine.common.header.ColumnHeaderConstant;
2323
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.SingleChildProcessNode;
24-
import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
25-
26-
import org.apache.tsfile.utils.ReadWriteIOUtils;
2724

2825
import java.io.DataOutputStream;
2926
import java.io.IOException;
@@ -60,36 +57,21 @@ public List<String> getOutputColumnNames() {
6057
return Collections.singletonList(ColumnHeaderConstant.EXPLAIN_ANALYZE);
6158
}
6259

63-
@Override
64-
public List<Symbol> getOutputSymbols() {
65-
return Collections.singletonList(Symbol.of(ColumnHeaderConstant.EXPLAIN_ANALYZE));
66-
}
67-
6860
@Override
6961
public PlanNode replaceChildren(List<PlanNode> newChildren) {
7062
return new ExplainAnalyzeNode(getPlanNodeId(), newChildren.get(0), verbose, queryId, timeout);
7163
}
7264

65+
// ExplainAnalyze should be at the same region as Coordinator all the time. Therefore, there will
66+
// be no serialization and deserialization process.
7367
@Override
7468
protected void serializeAttributes(ByteBuffer byteBuffer) {
75-
PlanNodeType.EXPLAIN_ANALYZE.serialize(byteBuffer);
76-
ReadWriteIOUtils.write(verbose, byteBuffer);
69+
throw new UnsupportedOperationException("ExplainAnalyzeNode should not be serialized");
7770
}
7871

7972
@Override
8073
protected void serializeAttributes(DataOutputStream stream) throws IOException {
81-
PlanNodeType.EXPLAIN_ANALYZE.serialize(stream);
82-
ReadWriteIOUtils.write(verbose, stream);
83-
ReadWriteIOUtils.write(queryId, stream);
84-
ReadWriteIOUtils.write(timeout, stream);
85-
}
86-
87-
public static ExplainAnalyzeNode deserialize(ByteBuffer byteBuffer) {
88-
boolean verbose = ReadWriteIOUtils.readBool(byteBuffer);
89-
long queryId = ReadWriteIOUtils.readLong(byteBuffer);
90-
PlanNodeId planNodeId = PlanNodeId.deserialize(byteBuffer);
91-
long timeout = ReadWriteIOUtils.readLong(byteBuffer);
92-
return new ExplainAnalyzeNode(planNodeId, null, verbose, queryId, timeout);
74+
throw new UnsupportedOperationException("ExplainAnalyzeNode should not be serialized");
9375
}
9476

9577
public boolean isVerbose() {

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanNodeType.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ public enum PlanNodeType {
276276
TABLE_AGGREGATION_NODE((short) 1015),
277277
TABLE_AGGREGATION_TABLE_SCAN_NODE((short) 1016),
278278
TABLE_GAP_FILL_NODE((short) 1017),
279+
TABLE_EXPLAIN_ANALYZE_NODE((short) 1018),
279280

280281
RELATIONAL_INSERT_TABLET((short) 2000),
281282
RELATIONAL_INSERT_ROW((short) 2001),
@@ -536,7 +537,7 @@ public static PlanNode deserialize(ByteBuffer buffer, short nodeType) {
536537
case 89:
537538
return AggregationMergeSortNode.deserialize(buffer);
538539
case 90:
539-
return ExplainAnalyzeNode.deserialize(buffer);
540+
throw new UnsupportedOperationException("ExplainAnalyzeNode should not be serialized");
540541
case 91:
541542
return PipeOperateSchemaQueueNode.deserialize(buffer);
542543
case 92:
@@ -626,6 +627,8 @@ public static PlanNode deserialize(ByteBuffer buffer, short nodeType) {
626627
.deserialize(buffer);
627628
case 1017:
628629
return GapFillNode.deserialize(buffer);
630+
case 1018:
631+
throw new UnsupportedOperationException("ExplainAnalyzeNode should not be deserialized");
629632
case 2000:
630633
return RelationalInsertTabletNode.deserialize(buffer);
631634
case 2001:

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanVisitor.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,12 @@ public R visitMergeSort(
666666
return visitMultiChildProcess(node, context);
667667
}
668668

669+
public R visitExplainAnalyze(
670+
org.apache.iotdb.db.queryengine.plan.relational.planner.node.ExplainAnalyzeNode node,
671+
C context) {
672+
return visitSingleChildProcess(node, context);
673+
}
674+
669675
public R visitOutput(
670676
org.apache.iotdb.db.queryengine.plan.relational.planner.node.OutputNode node, C context) {
671677
return visitSingleChildProcess(node, context);

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analysis.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ public class Analysis implements IAnalysis {
201201
// if emptyDataSource, there is no need to execute the query in BE
202202
private boolean emptyDataSource = false;
203203

204+
private boolean isQuery = false;
205+
204206
public DataPartition getDataPartition() {
205207
return dataPartition;
206208
}
@@ -752,7 +754,11 @@ public TsBlock constructResultForMemorySource(MPPQueryContext context) {
752754

753755
@Override
754756
public boolean isQuery() {
755-
return getStatement().isQuery();
757+
return isQuery;
758+
}
759+
760+
public void setQuery(boolean query) {
761+
isQuery = query;
756762
}
757763

758764
@Override

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/Analyzer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public Analysis analyze(Statement statement) {
9090
analysis, context, session, warningCollector, CorrelationSupport.ALLOWED);
9191

9292
analyzer.analyze(statement);
93-
if (statement.isQuery()) {
93+
if (analysis.isQuery()) {
9494
long analyzeCost = System.nanoTime() - startTime;
9595
QueryPlanCostMetricSet.getInstance().recordPlanCost(TABLE_TYPE, ANALYZER, analyzeCost);
9696
context.setAnalyzeCost(analyzeCost);

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/analyzer/StatementAnalyzer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ protected Scope visitExplainAnalyze(ExplainAnalyze node, Optional<Scope> context
601601

602602
@Override
603603
protected Scope visitQuery(Query node, Optional<Scope> context) {
604+
analysis.setQuery(true);
604605
Scope withScope = analyzeWith(node, context);
605606
hasFillInParentScope = node.getFill().isPresent() || hasFillInParentScope;
606607
Scope queryBodyScope = process(node.getQueryBody(), withScope);

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/TableLogicalPlanner.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector;
2626
import org.apache.iotdb.db.queryengine.metric.QueryPlanCostMetricSet;
2727
import org.apache.iotdb.db.queryengine.plan.planner.plan.LogicalQueryPlan;
28-
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.ExplainAnalyzeNode;
2928
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
3029
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.WritePlanNode;
3130
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.read.CountSchemaMergeNode;
@@ -34,6 +33,7 @@
3433
import org.apache.iotdb.db.queryengine.plan.relational.analyzer.RelationType;
3534
import org.apache.iotdb.db.queryengine.plan.relational.execution.querystats.PlanOptimizersStatsCollector;
3635
import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
36+
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.ExplainAnalyzeNode;
3737
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.FilterNode;
3838
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.LimitNode;
3939
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.OffsetNode;
@@ -67,6 +67,7 @@
6767
import com.google.common.collect.ImmutableMap;
6868
import org.apache.tsfile.enums.TSDataType;
6969
import org.apache.tsfile.read.common.type.LongType;
70+
import org.apache.tsfile.read.common.type.StringType;
7071
import org.apache.tsfile.read.common.type.TypeFactory;
7172

7273
import java.util.ArrayList;
@@ -127,7 +128,7 @@ public LogicalQueryPlan plan(final Analysis analysis) {
127128
final Statement statement = analysis.getStatement();
128129
PlanNode planNode = planStatement(analysis, statement);
129130

130-
if (statement.isQuery()) {
131+
if (analysis.isQuery()) {
131132
long logicalPlanCostTime = System.nanoTime() - startTime;
132133
QueryPlanCostMetricSet.getInstance()
133134
.recordPlanCost(TABLE_TYPE, LOGICAL_PLANNER, logicalPlanCostTime);
@@ -448,13 +449,16 @@ private void planTraverseDevice(final AbstractTraverseDevice statement, final An
448449
private RelationPlan planExplainAnalyze(final ExplainAnalyze statement, final Analysis analysis) {
449450
RelationPlan originalQueryPlan =
450451
createRelationPlan(analysis, (Query) (statement.getStatement()));
452+
Symbol symbol =
453+
symbolAllocator.newSymbol(ColumnHeaderConstant.EXPLAIN_ANALYZE, StringType.getInstance());
451454
PlanNode newRoot =
452455
new ExplainAnalyzeNode(
453456
queryContext.getQueryId().genPlanNodeId(),
454457
originalQueryPlan.getRoot(),
455458
statement.isVerbose(),
456459
queryContext.getLocalQueryId(),
457-
queryContext.getTimeOut());
460+
queryContext.getTimeOut(),
461+
symbol);
458462
return new RelationPlan(
459463
newRoot,
460464
originalQueryPlan.getScope(),

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/distribute/AddExchangeNodes.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,21 @@
2020
package org.apache.iotdb.db.queryengine.plan.relational.planner.distribute;
2121

2222
import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet;
23+
import org.apache.iotdb.commons.partition.DataPartition;
2324
import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
2425
import org.apache.iotdb.db.queryengine.plan.planner.distribution.NodeDistribution;
25-
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.ExplainAnalyzeNode;
2626
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode;
2727
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanVisitor;
2828
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.WritePlanNode;
2929
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.metadata.read.TableDeviceSourceNode;
3030
import org.apache.iotdb.db.queryengine.plan.planner.plan.node.process.ExchangeNode;
31+
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.ExplainAnalyzeNode;
3132
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNode;
3233
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.schema.TableDeviceFetchNode;
3334
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.schema.TableDeviceQueryCountNode;
3435
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.schema.TableDeviceQueryScanNode;
3536

37+
import static org.apache.iotdb.db.queryengine.plan.planner.distribution.NodeDistributionType.DIFFERENT_FROM_ALL_CHILDREN;
3638
import static org.apache.iotdb.db.queryengine.plan.planner.distribution.NodeDistributionType.SAME_WITH_ALL_CHILDREN;
3739
import static org.apache.iotdb.db.queryengine.plan.planner.distribution.NodeDistributionType.SAME_WITH_SOME_CHILD;
3840

@@ -59,14 +61,14 @@ public PlanNode visitPlan(PlanNode node, TableDistributedPlanGenerator.PlanConte
5961
PlanNode newNode = node.clone();
6062
if (node.getChildren().size() == 1) {
6163
newNode.addChild(node.getChildren().get(0).accept(this, context));
62-
// Explain Analyze doesn't have region info, this may be solved by a local RegionReplicaSet
63-
NodeDistribution childRegion =
64-
context.nodeDistributionMap.get(node.getChildren().get(0).getPlanNodeId());
65-
if (childRegion != null) {
66-
context.nodeDistributionMap.put(
67-
node.getPlanNodeId(),
68-
new NodeDistribution(SAME_WITH_ALL_CHILDREN, childRegion.getRegion()));
69-
}
64+
context.nodeDistributionMap.put(
65+
node.getPlanNodeId(),
66+
new NodeDistribution(
67+
SAME_WITH_ALL_CHILDREN,
68+
context
69+
.nodeDistributionMap
70+
.get(node.getChildren().get(0).getPlanNodeId())
71+
.getRegion()));
7072
return newNode;
7173
}
7274

@@ -134,6 +136,9 @@ public PlanNode visitExplainAnalyze(
134136
exchangeNode.setOutputSymbols(child.getOutputSymbols());
135137
newNode.setChild(exchangeNode);
136138

139+
context.nodeDistributionMap.put(
140+
newNode.getPlanNodeId(),
141+
new NodeDistribution(DIFFERENT_FROM_ALL_CHILDREN, DataPartition.NOT_ASSIGNED));
137142
context.hasExchangeNode = true;
138143
return newNode;
139144
}

0 commit comments

Comments
 (0)