You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by hy...@apache.org on 2020/05/01 12:04:02 UTC
[calcite] branch master updated: [CALCITE-3928] Trim unused fields
before materialized view matching (dz)
This is an automated email from the ASF dual-hosted git repository.
hyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new 24dd266 [CALCITE-3928] Trim unused fields before materialized view matching (dz)
24dd266 is described below
commit 24dd26640db01114c6931d6615b90a63969ffc42
Author: xzh <95...@qq.com>
AuthorDate: Tue Apr 21 18:54:31 2020 +0800
[CALCITE-3928] Trim unused fields before materialized view matching (dz)
Close #1936
---
.../calcite/plan/RelOptMaterializations.java | 22 +++++
.../materialize/NormalizationTrimFieldTest.java | 103 +++++++++++++++++++++
2 files changed, 125 insertions(+)
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java b/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java
index e6f1dbd..d06ec2b 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptMaterializations.java
@@ -21,6 +21,7 @@ import org.apache.calcite.plan.hep.HepPlanner;
import org.apache.calcite.plan.hep.HepProgram;
import org.apache.calcite.plan.hep.HepProgramBuilder;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.RelFactories;
import org.apache.calcite.rel.rules.CalcMergeRule;
import org.apache.calcite.rel.rules.FilterAggregateTransposeRule;
import org.apache.calcite.rel.rules.FilterCalcMergeRule;
@@ -34,6 +35,8 @@ import org.apache.calcite.rel.rules.ProjectMergeRule;
import org.apache.calcite.rel.rules.ProjectRemoveRule;
import org.apache.calcite.rel.rules.ProjectSetOpTransposeRule;
import org.apache.calcite.rel.rules.ProjectToCalcRule;
+import org.apache.calcite.sql2rel.RelFieldTrimmer;
+import org.apache.calcite.tools.RelBuilder;
import org.apache.calcite.util.Pair;
import org.apache.calcite.util.graph.DefaultDirectedGraph;
import org.apache.calcite.util.graph.DefaultEdge;
@@ -192,6 +195,9 @@ public abstract class RelOptMaterializations {
// Push filters to the bottom, and combine projects on top.
RelNode target = materialization.queryRel;
+ // try to trim unused field in relational expressions.
+ root = trimUnusedfields(root);
+ target = trimUnusedfields(target);
HepProgram program =
new HepProgramBuilder()
.addRuleInstance(FilterProjectTransposeRule.INSTANCE)
@@ -224,6 +230,22 @@ public abstract class RelOptMaterializations {
}
/**
+ * Trim unused fields in relational expressions.
+ */
+ private static RelNode trimUnusedfields(RelNode relNode) {
+ final List<RelOptTable> relOptTables = RelOptUtil.findAllTables(relNode);
+ RelOptSchema relOptSchema = null;
+ if (relOptTables.size() != 0) {
+ relOptSchema = relOptTables.get(0).getRelOptSchema();
+ }
+ final RelBuilder relBuilder = RelFactories.LOGICAL_BUILDER.create(
+ relNode.getCluster(), relOptSchema);
+ final RelFieldTrimmer relFieldTrimmer = new RelFieldTrimmer(null, relBuilder);
+ final RelNode rel = relFieldTrimmer.trim(relNode);
+ return rel;
+ }
+
+ /**
* Returns whether {@code table} uses one or more of the tables in
* {@code usedTables}.
*/
diff --git a/core/src/test/java/org/apache/calcite/materialize/NormalizationTrimFieldTest.java b/core/src/test/java/org/apache/calcite/materialize/NormalizationTrimFieldTest.java
new file mode 100644
index 0000000..567d952
--- /dev/null
+++ b/core/src/test/java/org/apache/calcite/materialize/NormalizationTrimFieldTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.calcite.materialize;
+
+import org.apache.calcite.plan.RelOptMaterialization;
+import org.apache.calcite.plan.RelOptMaterializations;
+import org.apache.calcite.plan.RelOptUtil;
+import org.apache.calcite.plan.RelTraitDef;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.AggregateCall;
+import org.apache.calcite.rel.logical.LogicalAggregate;
+import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.schema.SchemaPlus;
+import org.apache.calcite.schema.impl.AbstractTable;
+import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.test.CalciteAssert;
+import org.apache.calcite.test.SqlToRelTestBase;
+import org.apache.calcite.tools.Frameworks;
+import org.apache.calcite.tools.RelBuilder;
+import org.apache.calcite.util.ImmutableBitSet;
+import org.apache.calcite.util.Pair;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.apache.calcite.test.Matchers.isLinux;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class NormalizationTrimFieldTest extends SqlToRelTestBase {
+
+ public static Frameworks.ConfigBuilder config() {
+ final SchemaPlus rootSchema = Frameworks.createRootSchema(true);
+ rootSchema.add("mv0", new AbstractTable() {
+ @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
+ return typeFactory.builder()
+ .add("deptno", SqlTypeName.INTEGER)
+ .add("count_sal", SqlTypeName.BIGINT)
+ .build();
+ }
+ });
+ return Frameworks.newConfigBuilder()
+ .parserConfig(SqlParser.Config.DEFAULT)
+ .defaultSchema(
+ CalciteAssert.addSchema(rootSchema, CalciteAssert.SchemaSpec.SCOTT_WITH_TEMPORAL))
+ .traitDefs((List<RelTraitDef>) null);
+ }
+
+ @Test public void testMVTrimUnusedFiled() {
+ final RelBuilder relBuilder = RelBuilder.create(config().build());
+ final LogicalProject project = (LogicalProject) relBuilder.scan("EMP")
+ .project(relBuilder.field("EMPNO"),
+ relBuilder.field("ENAME"),
+ relBuilder.field("JOB"),
+ relBuilder.field("SAL"),
+ relBuilder.field("DEPTNO")).build();
+ final LogicalAggregate aggregate = (LogicalAggregate) relBuilder.push(project)
+ .aggregate(
+ relBuilder.groupKey(relBuilder.field(1, 0, "DEPTNO")
+ ), relBuilder.count(relBuilder.field(1, 0, "SAL"))).build();
+ final ImmutableBitSet groupSet = ImmutableBitSet.of(4);
+ final AggregateCall count = aggregate.getAggCallList().get(0);
+ final AggregateCall call = AggregateCall.create(count.getAggregation(), count.isDistinct(),
+ count.isApproximate(), count.ignoreNulls(), ImmutableList.of(3),
+ count.filterArg, count.collation, count.getType(), count.getName());
+ final RelNode query = LogicalAggregate.create(project, aggregate.getHints(),
+ groupSet, ImmutableList.of(groupSet), ImmutableList.of(call));
+ final RelNode target = aggregate;
+ final RelNode replacement = relBuilder.scan("mv0").build();
+ final RelOptMaterialization relOptMaterialization = new RelOptMaterialization(replacement,
+ target, null, Lists.newArrayList("mv0"));
+ final List<Pair<RelNode, List<RelOptMaterialization>>> relOptimized = RelOptMaterializations
+ .useMaterializedViews(query, ImmutableList.of(relOptMaterialization));
+
+ final String optimized = ""
+ + "LogicalProject(deptno=[CAST($0):TINYINT], count_sal=[$1])\n"
+ + " LogicalTableScan(table=[[mv0]])\n";
+ final String relOptimizedStr = RelOptUtil.toString(relOptimized.get(0).getKey());
+ assertThat(isLinux(optimized).matches(relOptimizedStr), is(true));
+ }
+}