calcite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jh...@apache.org
Subject calcite git commit: [CALCITE-2104] Add variants of AggregateUnionAggregateRule that match left and right inputs of Union, to reduce matching cost in VolcanoPlanner (lincoln-lil)
Date Wed, 27 Dec 2017 00:36:14 GMT
Repository: calcite
Updated Branches:
  refs/heads/master cb8376b13 -> 879139fc6


[CALCITE-2104] Add variants of AggregateUnionAggregateRule that match left and right inputs
of Union, to reduce matching cost in VolcanoPlanner (lincoln-lil)

Close apache/calcite#589


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/879139fc
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/879139fc
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/879139fc

Branch: refs/heads/master
Commit: 879139fc616ae954f5ebcbd53cb3b23c239a9a92
Parents: cb8376b
Author: lincoln-lil <lincoln.lil@alibaba-inc.com>
Authored: Thu Dec 21 15:38:57 2017 +0800
Committer: Julian Hyde <jhyde@apache.org>
Committed: Sun Dec 24 22:43:33 2017 -0800

----------------------------------------------------------------------
 .../rel/rules/AggregateUnionAggregateRule.java  | 48 +++++++++++++++-----
 .../apache/calcite/test/RelOptRulesTest.java    | 34 ++++++++++----
 .../org/apache/calcite/test/RelOptRulesTest.xml | 27 +++++++++++
 3 files changed, 88 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/879139fc/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionAggregateRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionAggregateRule.java
b/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionAggregateRule.java
index 8eeaaa7..a15d74a 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionAggregateRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/AggregateUnionAggregateRule.java
@@ -39,9 +39,31 @@ import org.apache.calcite.tools.RelBuilderFactory;
  * still have only two inputs.
  */
 public class AggregateUnionAggregateRule extends RelOptRule {
+  /** Instance that matches an {@code Aggregate} as the left input of
+   * {@code Union}. */
+  public static final AggregateUnionAggregateRule AGG_ON_FIRST_INPUT =
+      new AggregateUnionAggregateRule(LogicalAggregate.class, LogicalUnion.class,
+          LogicalAggregate.class, RelNode.class, RelFactories.LOGICAL_BUILDER,
+          "AggregateUnionAggregateRule:first-input-agg");
+
+  /** Instance that matches an {@code Aggregate} as the right input of
+   * {@code Union}. */
+  public static final AggregateUnionAggregateRule AGG_ON_SECOND_INPUT =
+      new AggregateUnionAggregateRule(LogicalAggregate.class, LogicalUnion.class,
+          RelNode.class, LogicalAggregate.class, RelFactories.LOGICAL_BUILDER,
+          "AggregateUnionAggregateRule:second-input-agg");
+
+  /** Instance that matches an {@code Aggregate} as either input of
+   * {@link Union}.
+   *
+   * <p>Because it matches {@link RelNode} for each input of {@code Union}, it
+   * will create O(N ^ 2) matches, which may cost too much during the popMatch
+   * phase in VolcanoPlanner. If efficiency is a concern, we recommend that you
+   * use {@link #AGG_ON_FIRST_INPUT} and {@link #AGG_ON_SECOND_INPUT} instead. */
   public static final AggregateUnionAggregateRule INSTANCE =
       new AggregateUnionAggregateRule(LogicalAggregate.class,
-          LogicalUnion.class, RelFactories.LOGICAL_BUILDER);
+          LogicalUnion.class, RelNode.class, RelNode.class,
+          RelFactories.LOGICAL_BUILDER, "AggregateUnionAggregateRule");
 
   //~ Constructors -----------------------------------------------------------
 
@@ -49,13 +71,17 @@ public class AggregateUnionAggregateRule extends RelOptRule {
    * Creates a AggregateUnionAggregateRule.
    */
   public AggregateUnionAggregateRule(Class<? extends Aggregate> aggregateClass,
-      Class<? extends Union> unionClass, RelBuilderFactory relBuilderFactory) {
+      Class<? extends Union> unionClass,
+      Class<? extends RelNode> firstUnionInputClass,
+      Class<? extends RelNode> secondUnionInputClass,
+      RelBuilderFactory relBuilderFactory,
+      String desc) {
     super(
         operand(aggregateClass, null, Aggregate.IS_SIMPLE,
             operand(unionClass,
-                operand(RelNode.class, any()),
-                operand(RelNode.class, any()))),
-        relBuilderFactory, null);
+                operand(firstUnionInputClass, any()),
+                operand(secondUnionInputClass, any()))),
+        relBuilderFactory, desc);
   }
 
   @Deprecated // to be removed before 2.0
@@ -63,8 +89,9 @@ public class AggregateUnionAggregateRule extends RelOptRule {
       RelFactories.AggregateFactory aggregateFactory,
       Class<? extends Union> unionClass,
       RelFactories.SetOpFactory setOpFactory) {
-    this(aggregateClass, unionClass,
-        RelBuilder.proto(aggregateFactory, setOpFactory));
+    this(aggregateClass, unionClass, RelNode.class, RelNode.class,
+        RelBuilder.proto(aggregateFactory, setOpFactory),
+        "AggregateUnionAggregateRule");
   }
 
   //~ Methods ----------------------------------------------------------------
@@ -78,18 +105,15 @@ public class AggregateUnionAggregateRule extends RelOptRule {
       return;
     }
 
-    // We want to apply this rule on the pattern where the LogicalAggregate
-    // is the second input into the Union first.  Hence, that's why the
-    // rule pattern matches on generic RelNodes rather than explicit
-    // UnionRels.  By doing so, and firing this rule in a bottom-up order,
-    // it allows us to only specify a single pattern for this rule.
     final RelBuilder relBuilder = call.builder();
     final Aggregate bottomAggRel;
     if (call.rel(3) instanceof Aggregate) {
+      // Aggregate is the second input
       bottomAggRel = call.rel(3);
       relBuilder.push(call.rel(2))
           .push(call.rel(3).getInput(0));
     } else if (call.rel(2) instanceof Aggregate) {
+      // Aggregate is the first input
       bottomAggRel = call.rel(2);
       relBuilder.push(call.rel(2).getInput(0))
           .push(call.rel(3));

http://git-wip-us.apache.org/repos/asf/calcite/blob/879139fc/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
index 321d9fc..a738a00 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -2514,19 +2514,35 @@ public class RelOptRulesTest extends RelOptTestBase {
             + "group by rollup(x, y)");
   }
 
-  @Test public void testPullAggregateThroughUnion() throws Exception {
+  @Test public void testPullAggregateThroughUnion() {
     HepProgram program = new HepProgramBuilder()
         .addRuleInstance(AggregateUnionAggregateRule.INSTANCE)
         .build();
 
-    checkPlanning(program,
-        "select deptno, job from"
-            + " (select deptno, job from emp as e1"
-            + " group by deptno,job"
-            + "  union all"
-            + " select deptno, job from emp as e2"
-            + " group by deptno,job)"
-            + " group by deptno,job");
+    final String sql = "select deptno, job from"
+        + " (select deptno, job from emp as e1"
+        + " group by deptno,job"
+        + "  union all"
+        + " select deptno, job from emp as e2"
+        + " group by deptno,job)"
+        + " group by deptno,job";
+    sql(sql).with(program).check();
+  }
+
+  @Test public void testPullAggregateThroughUnion2() {
+    HepProgram program = new HepProgramBuilder()
+        .addRuleInstance(AggregateUnionAggregateRule.AGG_ON_SECOND_INPUT)
+        .addRuleInstance(AggregateUnionAggregateRule.AGG_ON_FIRST_INPUT)
+        .build();
+
+    final String sql = "select deptno, job from"
+        + " (select deptno, job from emp as e1"
+        + " group by deptno,job"
+        + "  union all"
+        + " select deptno, job from emp as e2"
+        + " group by deptno,job)"
+        + " group by deptno,job";
+    sql(sql).with(program).check();
   }
 
   private void transitiveInference(RelOptRule... extraRules) throws Exception {

http://git-wip-us.apache.org/repos/asf/calcite/blob/879139fc/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
index 46518f9..d573517 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -5035,6 +5035,33 @@ LogicalAggregate(group=[{0, 1}])
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testPullAggregateThroughUnion2">
+        <Resource name="sql">
+            <![CDATA[select deptno, job from (select deptno, job from emp as e1 group
by deptno,job  union all select deptno, job from emp as e2 group by deptno,job) group by deptno,job]]>
+        </Resource>
+        <Resource name="planBefore">
+            <![CDATA[
+LogicalAggregate(group=[{0, 1}])
+  LogicalUnion(all=[true])
+    LogicalAggregate(group=[{0, 1}])
+      LogicalProject(DEPTNO=[$7], JOB=[$2])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+    LogicalAggregate(group=[{0, 1}])
+      LogicalProject(DEPTNO=[$7], JOB=[$2])
+        LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+        <Resource name="planAfter">
+            <![CDATA[
+LogicalAggregate(group=[{0, 1}])
+  LogicalUnion(all=[true])
+    LogicalProject(DEPTNO=[$7], JOB=[$2])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+    LogicalProject(DEPTNO=[$7], JOB=[$2])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testProjectWindowTransposeRule">
         <Resource name="sql">
             <![CDATA[select count(empno) over(), deptno from emp]]>


Mime
View raw message