This is an automated email from the ASF dual-hosted git repository. caogaofei pushed a commit to branch ty/TableModelGrammar in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/ty/TableModelGrammar by this push: new dbb378c3c02 Fix sort elimination, perfect explain output dbb378c3c02 is described below commit dbb378c3c02882ebf315e0bba74d1b0e805b6d0b Author: Beyyes <cgf1...@foxmail.com> AuthorDate: Wed Jul 24 16:51:20 2024 +0800 Fix sort elimination, perfect explain output --- .../TableModelStatementMemorySourceVisitor.java | 34 ++++++++++++++++++++-- .../plan/planner/plan/node/PlanGraphPrinter.java | 10 +++++++ .../planner/optimizations/SortElimination.java | 19 ++++++++++-- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java index ec9c5d145f3..d92db81e1bd 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/execution/memory/TableModelStatementMemorySourceVisitor.java @@ -22,13 +22,17 @@ package org.apache.iotdb.db.queryengine.plan.execution.memory; import org.apache.iotdb.commons.conf.IoTDBConstant; import org.apache.iotdb.db.queryengine.common.header.ColumnHeader; import org.apache.iotdb.db.queryengine.common.header.DatasetHeader; -import org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector; import org.apache.iotdb.db.queryengine.plan.planner.LocalExecutionPlanner; import org.apache.iotdb.db.queryengine.plan.planner.plan.LogicalQueryPlan; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanGraphPrinter; import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNode; +import org.apache.iotdb.db.queryengine.plan.relational.execution.querystats.PlanOptimizersStatsCollector; +import org.apache.iotdb.db.queryengine.plan.relational.planner.SymbolAllocator; import org.apache.iotdb.db.queryengine.plan.relational.planner.distribute.AddExchangeNodes; import org.apache.iotdb.db.queryengine.plan.relational.planner.distribute.DistributedPlanGenerator; +import org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.PlanOptimizer; +import org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.PushLimitOffsetIntoTableScan; +import org.apache.iotdb.db.queryengine.plan.relational.planner.optimizations.SortElimination; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.AstVisitor; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Explain; import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node; @@ -36,11 +40,13 @@ import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node; import org.apache.tsfile.enums.TSDataType; import org.apache.tsfile.read.common.block.TsBlock; +import java.util.Arrays; import java.util.Collections; import java.util.List; import static com.google.common.base.Preconditions.checkArgument; import static org.apache.iotdb.db.queryengine.common.header.DatasetHeader.EMPTY_HEADER; +import static org.apache.iotdb.db.queryengine.execution.warnings.WarningCollector.NOOP; import static org.apache.iotdb.db.queryengine.plan.execution.memory.StatementMemorySourceVisitor.getStatementMemorySource; public class TableModelStatementMemorySourceVisitor @@ -68,7 +74,7 @@ public class TableModelStatementMemorySourceVisitor context.getQueryContext(), LocalExecutionPlanner.getInstance().metadata, context.getQueryContext().getSession(), - WarningCollector.NOOP) + NOOP) .plan(context.getAnalysis()); if (context.getAnalysis().isEmptyDataSource()) { return new StatementMemorySource(new TsBlock(0), header); @@ -81,10 +87,32 @@ public class TableModelStatementMemorySourceVisitor .genResult(logicalPlan.getRootNode(), planContext); checkArgument(distributedPlanResult.size() == 1, "Root node must return only one"); + // Notice: when change the optimizers in TableDistributionPlanner, these code also need to be + // adapted + List<PlanOptimizer> optimizers = + Arrays.asList(new PushLimitOffsetIntoTableScan(), new SortElimination()); + // distribute plan optimize rule + PlanNode distributedPlan = distributedPlanResult.get(0); + for (PlanOptimizer optimizer : optimizers) { + distributedPlan = + optimizer.optimize( + distributedPlan, + new PlanOptimizer.Context( + null, + context.getAnalysis(), + null, + context.getQueryContext(), + context.getQueryContext().getTypeProvider(), + new SymbolAllocator(), + context.getQueryContext().getQueryId(), + NOOP, + PlanOptimizersStatsCollector.createPlanOptimizersStatsCollector())); + } + // add exchange node for distributed plan PlanNode outputNodeWithExchange = new AddExchangeNodes(context.getQueryContext()) - .addExchangeNodes(distributedPlanResult.get(0), planContext); + .addExchangeNodes(distributedPlan, planContext); List<String> lines = outputNodeWithExchange.accept( diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java index c55996874f9..9a0ea93d608 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java @@ -698,6 +698,16 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter return render(node, boxValue, context); } + @Override + public List<String> visitCollect( + org.apache.iotdb.db.queryengine.plan.relational.planner.node.CollectNode node, + GraphContext context) { + List<String> boxValue = new ArrayList<>(); + boxValue.add(String.format("Collect-%s", node.getPlanNodeId().getId())); + boxValue.add(String.format("OutputSymbols: %s", node.getOutputSymbols())); + return render(node, boxValue, context); + } + private String printRegion(TRegionReplicaSet regionReplicaSet) { return String.format( "Partition: %s", diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SortElimination.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SortElimination.java index 23bb78c8da4..6ab922361a7 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SortElimination.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/SortElimination.java @@ -68,10 +68,11 @@ public class SortElimination implements PlanOptimizer { @Override public PlanNode visitSort(SortNode node, Context context) { - PlanNode child = node.getChild().accept(this, context); - TableScanNode tableScanNode = context.getTableScanNode(); + Context newContext = new Context(); + PlanNode child = node.getChild().accept(this, newContext); OrderingScheme orderingScheme = node.getOrderingScheme(); - if (tableScanNode.getDeviceEntries().size() == 1 + TableScanNode tableScanNode = newContext.getTableScanNode(); + if (newContext.getTotalDeviceEntrySize() == 1 && TIMESTAMP_STR.equalsIgnoreCase(orderingScheme.getOrderBy().get(0).getName())) { return child; } @@ -87,6 +88,7 @@ public class SortElimination implements PlanOptimizer { @Override public PlanNode visitTableScan(TableScanNode node, Context context) { + context.addDeviceEntrySize(node.getDeviceEntries().size()); context.setTableScanNode(node); return node; } @@ -121,8 +123,19 @@ public class SortElimination implements PlanOptimizer { } private static class Context { + private int totalDeviceEntrySize = 0; private TableScanNode tableScanNode; + Context() {} + + public void addDeviceEntrySize(int deviceEntrySize) { + this.totalDeviceEntrySize += deviceEntrySize; + } + + public int getTotalDeviceEntrySize() { + return totalDeviceEntrySize; + } + public TableScanNode getTableScanNode() { return tableScanNode; }