This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.0 by this push:
new 1a2d3bb520f [improvement](Nereids) Support to remove sort which is
under table sink (#31751) (#32262)
1a2d3bb520f is described below
commit 1a2d3bb520fdda33ea18d6bde17f3795114b8988
Author: seawinde <[email protected]>
AuthorDate: Fri Mar 15 11:50:22 2024 +0800
[improvement](Nereids) Support to remove sort which is under table sink
(#31751) (#32262)
cherry-pick
pr #31751
commit id: 67064e1
---
.../doris/nereids/rules/rewrite/EliminateSort.java | 15 ++-
.../trees/plans/logical/LogicalOlapTableSink.java | 2 +-
.../trees/plans/logical/LogicalTableSink.java | 43 ++++++++
.../plans/physical/PhysicalOlapTableSink.java | 2 +-
.../trees/plans/physical/PhysicalTableSink.java | 45 +++++++++
.../nereids/trees/plans/visitor/SinkVisitor.java | 10 ++
.../nereids/rules/rewrite/EliminateSortTest.java | 109 ++++++++++++++++++++-
7 files changed, 218 insertions(+), 8 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateSort.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateSort.java
index c08c5dfb266..9dd80771785 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateSort.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateSort.java
@@ -22,6 +22,7 @@ import org.apache.doris.nereids.trees.plans.Plan;
import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
import org.apache.doris.nereids.trees.plans.logical.LogicalSink;
import org.apache.doris.nereids.trees.plans.logical.LogicalSort;
+import org.apache.doris.nereids.trees.plans.logical.LogicalTableSink;
import org.apache.doris.nereids.trees.plans.visitor.CustomRewriter;
import org.apache.doris.nereids.trees.plans.visitor.DefaultPlanRewriter;
@@ -29,10 +30,10 @@ import java.util.ArrayList;
import java.util.List;
/**
- * Eliminate sort that is not directly below result sink
+ * Eliminate sort that is not directly below result sink, if there is project
between result sink and sort,
+ * the sort will not be eliminated.
* Note we have put limit in sort node so that we don't need to consider limit
*/
-
public class EliminateSort extends DefaultPlanRewriter<Boolean> implements
CustomRewriter {
@Override
public Plan rewriteRoot(Plan plan, JobContext jobContext) {
@@ -45,6 +46,7 @@ public class EliminateSort extends
DefaultPlanRewriter<Boolean> implements Custo
List<Plan> newChildren = new ArrayList<>();
boolean hasNewChildren = false;
for (Plan child : plan.children()) {
+ // eliminate sort default
Plan newChild = child.accept(this, true);
if (newChild != child) {
hasNewChildren = true;
@@ -64,12 +66,17 @@ public class EliminateSort extends
DefaultPlanRewriter<Boolean> implements Custo
@Override
public Plan visitLogicalProject(LogicalProject<? extends Plan> project,
Boolean eliminateSort) {
+ // sometimes there is project between logicalResultSink and sort,
should skip eliminate
return skipEliminateSort(project, eliminateSort);
}
@Override
- public Plan visitLogicalSink(LogicalSink<? extends Plan> sink, Boolean
eliminateSort) {
- return skipEliminateSort(sink, eliminateSort);
+ public Plan visitLogicalSink(LogicalSink<? extends Plan> logicalSink,
Boolean eliminateSort) {
+ if (logicalSink instanceof LogicalTableSink) {
+ // eliminate sort
+ return visit(logicalSink, true);
+ }
+ return skipEliminateSort(logicalSink, eliminateSort);
}
private Plan skipEliminateSort(Plan plan, Boolean eliminateSort) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOlapTableSink.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOlapTableSink.java
index b8962a4ba4a..ca880d2a664 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOlapTableSink.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalOlapTableSink.java
@@ -39,7 +39,7 @@ import java.util.Optional;
/**
* logical olap table sink for insert command
*/
-public class LogicalOlapTableSink<CHILD_TYPE extends Plan> extends
LogicalSink<CHILD_TYPE> implements Sink {
+public class LogicalOlapTableSink<CHILD_TYPE extends Plan> extends
LogicalTableSink<CHILD_TYPE> implements Sink {
// bound data sink
private Database database;
private OlapTable targetTable;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalTableSink.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalTableSink.java
new file mode 100644
index 00000000000..90133274f6e
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/logical/LogicalTableSink.java
@@ -0,0 +1,43 @@
+// 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.doris.nereids.trees.plans.logical;
+
+import org.apache.doris.nereids.memo.GroupExpression;
+import org.apache.doris.nereids.properties.LogicalProperties;
+import org.apache.doris.nereids.trees.expressions.NamedExpression;
+import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.PlanType;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Logical table sink for all table type sink
+ */
+public abstract class LogicalTableSink<CHILD_TYPE extends Plan> extends
LogicalSink<CHILD_TYPE> {
+ public LogicalTableSink(PlanType type,
+ List<NamedExpression> outputExprs, CHILD_TYPE child) {
+ super(type, outputExprs, child);
+ }
+
+ public LogicalTableSink(PlanType type, List<NamedExpression> outputExprs,
+ Optional<GroupExpression> groupExpression,
+ Optional<LogicalProperties> logicalProperties, CHILD_TYPE child) {
+ super(type, outputExprs, groupExpression, logicalProperties, child);
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapTableSink.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapTableSink.java
index e63d6a93fcf..9a65864f1e2 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapTableSink.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOlapTableSink.java
@@ -52,7 +52,7 @@ import java.util.stream.Collectors;
/**
* physical olap table sink for insert command
*/
-public class PhysicalOlapTableSink<CHILD_TYPE extends Plan> extends
PhysicalSink<CHILD_TYPE> implements Sink {
+public class PhysicalOlapTableSink<CHILD_TYPE extends Plan> extends
PhysicalTableSink<CHILD_TYPE> implements Sink {
private final Database database;
private final OlapTable targetTable;
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalTableSink.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalTableSink.java
new file mode 100644
index 00000000000..5932c4f0999
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalTableSink.java
@@ -0,0 +1,45 @@
+// 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.doris.nereids.trees.plans.physical;
+
+import org.apache.doris.nereids.memo.GroupExpression;
+import org.apache.doris.nereids.properties.LogicalProperties;
+import org.apache.doris.nereids.properties.PhysicalProperties;
+import org.apache.doris.nereids.trees.expressions.NamedExpression;
+import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.PlanType;
+import org.apache.doris.statistics.Statistics;
+
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Physical table sink for all table type sink
+ */
+public abstract class PhysicalTableSink<CHILD_TYPE extends Plan> extends
PhysicalSink<CHILD_TYPE> {
+
+ public PhysicalTableSink(PlanType type, List<NamedExpression> outputExprs,
+ Optional<GroupExpression> groupExpression,
+ LogicalProperties logicalProperties,
+ @Nullable PhysicalProperties physicalProperties,
+ Statistics statistics, CHILD_TYPE child) {
+ super(type, outputExprs, groupExpression, logicalProperties,
physicalProperties, statistics, child);
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/SinkVisitor.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/SinkVisitor.java
index df790fddd29..9ada0480187 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/SinkVisitor.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/visitor/SinkVisitor.java
@@ -25,11 +25,13 @@ import
org.apache.doris.nereids.trees.plans.logical.LogicalFileSink;
import org.apache.doris.nereids.trees.plans.logical.LogicalOlapTableSink;
import org.apache.doris.nereids.trees.plans.logical.LogicalResultSink;
import org.apache.doris.nereids.trees.plans.logical.LogicalSink;
+import org.apache.doris.nereids.trees.plans.logical.LogicalTableSink;
import
org.apache.doris.nereids.trees.plans.physical.PhysicalDeferMaterializeResultSink;
import org.apache.doris.nereids.trees.plans.physical.PhysicalFileSink;
import org.apache.doris.nereids.trees.plans.physical.PhysicalOlapTableSink;
import org.apache.doris.nereids.trees.plans.physical.PhysicalResultSink;
import org.apache.doris.nereids.trees.plans.physical.PhysicalSink;
+import org.apache.doris.nereids.trees.plans.physical.PhysicalTableSink;
/**
* sink visitor
@@ -64,6 +66,10 @@ public interface SinkVisitor<R, C> {
return visitLogicalSink(fileSink, context);
}
+ default R visitLogicalTableSink(LogicalTableSink<? extends Plan>
logicalTableSink, C context) {
+ return visitLogicalSink(logicalTableSink, context);
+ }
+
default R visitLogicalOlapTableSink(LogicalOlapTableSink<? extends Plan>
olapTableSink, C context) {
return visitLogicalSink(olapTableSink, context);
}
@@ -85,6 +91,10 @@ public interface SinkVisitor<R, C> {
return visitPhysicalSink(fileSink, context);
}
+ default R visitPhysicalTableSink(PhysicalTableSink<? extends Plan>
physicalTableSink, C context) {
+ return visitPhysicalSink(physicalTableSink, context);
+ }
+
default R visitPhysicalOlapTableSink(PhysicalOlapTableSink<? extends Plan>
olapTableSink, C context) {
return visitPhysicalSink(olapTableSink, context);
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateSortTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateSortTest.java
index cc039cbabb1..b75c762fb0e 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateSortTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/rewrite/EliminateSortTest.java
@@ -17,12 +17,24 @@
package org.apache.doris.nereids.rules.rewrite;
+import org.apache.doris.catalog.Database;
+import org.apache.doris.nereids.properties.OrderKey;
+import org.apache.doris.nereids.trees.expressions.NamedExpression;
+import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalOlapTableSink;
+import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
+import org.apache.doris.nereids.util.LogicalPlanBuilder;
import org.apache.doris.nereids.util.MemoPatternMatchSupported;
+import org.apache.doris.nereids.util.MemoTestUtils;
import org.apache.doris.nereids.util.PlanChecker;
+import org.apache.doris.nereids.util.PlanConstructor;
import org.apache.doris.utframe.TestWithFeService;
import org.junit.jupiter.api.Test;
+import java.util.ArrayList;
+import java.util.stream.Collectors;
+
/**
* column prune ut.
*/
@@ -37,15 +49,108 @@ class EliminateSortTest extends TestWithFeService
implements MemoPatternMatchSup
}
@Test
- void test() {
+ void testEliminateSortWhenCTE() {
+ PlanChecker.from(connectContext)
+ .analyze("with cte_test as (\n"
+ + "select id, name, age from student order by id\n"
+ + ")\n"
+ + "select * from cte_test c1\n"
+ + "join student\n"
+ + "join cte_test c2\n"
+ + "where c1.id = student.id")
+ .rewrite()
+ .nonMatch(logicalSort());
+
PlanChecker.from(connectContext)
- .analyze("select * from student order by id")
+ .analyze("with cte_test as (\n"
+ + "select id, name, age from student\n"
+ + ")\n"
+ + "select * from cte_test c1\n"
+ + "join student\n"
+ + "join cte_test c2\n"
+ + "where c1.id = student.id order by c1.age")
.rewrite()
.matches(logicalSort());
+
+ PlanChecker.from(connectContext)
+ .analyze("select t.age from\n"
+ + "(\n"
+ + "with cte_test as (\n"
+ + "select id, name, age from student order by id\n"
+ + ")\n"
+ + "select c1.id, student.name, c2.age from cte_test
c1\n"
+ + "join student\n"
+ + "join cte_test c2\n"
+ + "where c1.id = student.id order by c1.age\n"
+ + ") t order by t.id")
+ .rewrite()
+ .matches(logicalSort());
+ }
+
+ @Test
+ void testEliminateSortUnderTableSink() {
+ // topN under table sink should not be removed
+ LogicalOlapScan scan = PlanConstructor.newLogicalOlapScan(0, "t1", 0);
+ LogicalPlan plan = new LogicalPlanBuilder(scan)
+ .sort(scan.getOutput().stream().map(c -> new OrderKey(c, true,
true)).collect(Collectors.toList()))
+ .limit(1, 1).build();
+ plan = new LogicalOlapTableSink<>(new Database(), scan.getTable(),
scan.getTable().getBaseSchema(),
+ new ArrayList<>(),
plan.getOutput().stream().map(NamedExpression.class::cast).collect(
+ Collectors.toList()), false, false, plan);
+ PlanChecker.from(MemoTestUtils.createConnectContext(), plan)
+ .rewrite()
+ .nonMatch(logicalSort())
+ .matches(logicalTopN());
+
+ // sort under table sink should be removed
+ scan = PlanConstructor.newLogicalOlapScan(0, "t2", 0);
+ plan = new LogicalPlanBuilder(scan)
+ .sort(scan.getOutput().stream().map(c -> new OrderKey(c, true,
true)).collect(Collectors.toList()))
+ .build();
+ plan = new LogicalOlapTableSink<>(new Database(), scan.getTable(),
scan.getTable().getBaseSchema(),
+ new ArrayList<>(),
plan.getOutput().stream().map(NamedExpression.class::cast).collect(
+ Collectors.toList()), false, false, plan);
+ PlanChecker.from(MemoTestUtils.createConnectContext(), plan)
+ .rewrite()
+ .nonMatch(logicalSort());
+ }
+
+ @Test
+ void testEliminateSortInUnion() {
+ PlanChecker.from(connectContext)
+ .analyze("SELECT * FROM (SELECT * FROM student UNION SELECT *
FROM student ORDER BY id) u LIMIT 1")
+ .rewrite()
+ .nonMatch(logicalSort());
+ }
+
+ @Test
+ void testEliminateSortInSubquery() {
PlanChecker.from(connectContext)
.analyze("select count(*) from (select * from student order by
id) t")
.rewrite()
.nonMatch(logicalSort());
+ PlanChecker.from(connectContext)
+ .analyze("select \n"
+ + " id, \n"
+ + " name \n"
+ + "from \n"
+ + " (\n"
+ + " select \n"
+ + " id, \n"
+ + " name, \n"
+ + " age \n"
+ + " from \n"
+ + " (\n"
+ + " select \n"
+ + " * \n"
+ + " from \n"
+ + " student\n"
+ + " ) s \n"
+ + " order by \n"
+ + " id\n"
+ + " ) t")
+ .rewrite()
+ .nonMatch(logicalSort());
}
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]