This is an automated email from the ASF dual-hosted git repository.
jakevin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new dbccbe0fbba [feat](Nereids): add struct info map in group (#31800)
dbccbe0fbba is described below
commit dbccbe0fbbaaa6550eee7b3234c15910615c63a5
Author: 谢健 <[email protected]>
AuthorDate: Wed Mar 6 16:49:04 2024 +0800
[feat](Nereids): add struct info map in group (#31800)
---
.../org/apache/doris/mtmv/MTMVRelationManager.java | 10 +-
.../java/org/apache/doris/nereids/memo/Group.java | 7 +-
.../apache/doris/nereids/memo/StructInfoMap.java | 123 +++++++++++++++++++++
.../mv/InitMaterializationContextHook.java | 7 +-
.../doris/nereids/memo/StructInfoMapTest.java | 81 ++++++++++++++
.../org/apache/doris/nereids/util/PlanChecker.java | 2 +
.../apache/doris/utframe/TestWithFeService.java | 28 +++++
7 files changed, 252 insertions(+), 6 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelationManager.java
b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelationManager.java
index aa7ffd2426d..723deaff740 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelationManager.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVRelationManager.java
@@ -35,6 +35,7 @@ import
org.apache.doris.nereids.trees.plans.commands.info.TableNameInfo;
import org.apache.doris.persist.AlterMTMV;
import org.apache.doris.qe.ConnectContext;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -71,8 +72,7 @@ public class MTMVRelationManager implements MTMVHookService {
for (BaseTableInfo tableInfo : mvInfos) {
try {
MTMV mtmv = (MTMV) MTMVUtil.getTable(tableInfo);
- if (!CollectionUtils
-
.isEmpty(MTMVRewriteUtil.getMTMVCanRewritePartitions(mtmv, ctx,
System.currentTimeMillis()))) {
+ if (isMVPartitionValid(mtmv, ctx)) {
res.add(mtmv);
}
} catch (AnalysisException e) {
@@ -83,6 +83,12 @@ public class MTMVRelationManager implements MTMVHookService {
return res;
}
+ @VisibleForTesting
+ public boolean isMVPartitionValid(MTMV mtmv, ConnectContext ctx) {
+ return !CollectionUtils
+ .isEmpty(MTMVRewriteUtil.getMTMVCanRewritePartitions(mtmv,
ctx, System.currentTimeMillis()));
+ }
+
private Set<BaseTableInfo> getMTMVInfos(List<BaseTableInfo> tableInfos) {
Set<BaseTableInfo> mvInfos = Sets.newHashSet();
for (BaseTableInfo tableInfo : tableInfos) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java
index 2a0e83c72a4..5a5abd56f95 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/Group.java
@@ -19,7 +19,6 @@ package org.apache.doris.nereids.memo;
import org.apache.doris.common.Pair;
import org.apache.doris.nereids.cost.Cost;
-import org.apache.doris.nereids.jobs.joinorder.hypergraph.HyperGraph;
import org.apache.doris.nereids.properties.LogicalProperties;
import org.apache.doris.nereids.properties.PhysicalProperties;
import org.apache.doris.nereids.rules.exploration.mv.StructInfo;
@@ -78,6 +77,8 @@ public class Group {
private List<StructInfo> structInfos = new ArrayList<>();
+ private StructInfoMap structInfoMap = new StructInfoMap();
+
/**
* Constructor for Group.
*
@@ -418,8 +419,8 @@ public class Group {
return false;
}
- public List<HyperGraph> getHyperGraphs() {
- return new ArrayList<>();
+ public StructInfoMap getstructInfoMap() {
+ return structInfoMap;
}
public boolean isProjectGroup() {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/StructInfoMap.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/StructInfoMap.java
new file mode 100644
index 00000000000..f7e09fd44d9
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/memo/StructInfoMap.java
@@ -0,0 +1,123 @@
+// 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.memo;
+
+import org.apache.doris.nereids.rules.exploration.mv.StructInfo;
+import org.apache.doris.nereids.trees.plans.Plan;
+import org.apache.doris.nereids.trees.plans.logical.LogicalCatalogRelation;
+
+import com.google.common.collect.Sets;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+
+/**
+ * Representation for group in cascades optimizer.
+ */
+public class StructInfoMap {
+ private final Map<BitSet, GroupExpression> groupExpressionMap = new
HashMap<>();
+ private final Map<BitSet, StructInfo> infoMap = new HashMap<>();
+
+ /**
+ * get struct info according to table map
+ * @param mvTableMap the original table map
+ * @param foldTableMap the fold table map
+ * @param group the group that the mv matched
+ * @return struct info or null if not found
+ */
+ public @Nullable StructInfo getStructInfo(BitSet mvTableMap, BitSet
foldTableMap, Group group) {
+ if (!infoMap.containsKey(mvTableMap)) {
+ if ((groupExpressionMap.containsKey(foldTableMap) ||
groupExpressionMap.isEmpty())
+ && !groupExpressionMap.containsKey(mvTableMap)) {
+ refresh(group);
+ }
+ if (groupExpressionMap.containsKey(mvTableMap)) {
+ StructInfo structInfo =
constructStructInfo(groupExpressionMap.get(mvTableMap));
+ infoMap.put(mvTableMap, structInfo);
+ }
+ }
+
+ return infoMap.get(mvTableMap);
+ }
+
+ public Set<BitSet> getTableMaps() {
+ return groupExpressionMap.keySet();
+ }
+
+ private StructInfo constructStructInfo(GroupExpression groupExpression) {
+ throw new RuntimeException("has not been implemented for" +
groupExpression);
+ }
+
+ /**
+ * refresh group expression map
+ * @param group the root group
+ */
+ public void refresh(Group group) {
+ List<Set<BitSet>> childrenTableMap = new ArrayList<>();
+ Set<Group> refreshedGroup = new HashSet<>();
+ for (GroupExpression groupExpression : group.getLogicalExpressions()) {
+ if (groupExpression.children().isEmpty()) {
+ groupExpressionMap.put(constructLeaf(groupExpression),
groupExpression);
+ continue;
+ }
+ for (Group child : groupExpression.children()) {
+ if (!refreshedGroup.contains(child)) {
+ StructInfoMap childStructInfoMap =
child.getstructInfoMap();
+ childStructInfoMap.refresh(child);
+ }
+ refreshedGroup.add(child);
+ childrenTableMap.add(child.getstructInfoMap().getTableMaps());
+ }
+ Set<BitSet> bitSets = cartesianProduct(childrenTableMap);
+ for (BitSet bitSet : bitSets) {
+ groupExpressionMap.put(bitSet, groupExpression);
+ }
+ }
+ }
+
+ private BitSet constructLeaf(GroupExpression groupExpression) {
+ Plan plan = groupExpression.getPlan();
+ BitSet tableMap = new BitSet();
+ if (plan instanceof LogicalCatalogRelation) {
+ // TODO: Bitmap is not compatible with long, use tree map instead
+ tableMap.set((int) ((LogicalCatalogRelation)
plan).getTable().getId());
+ }
+ // one row relation / CTE consumer
+ return tableMap;
+ }
+
+ private Set<BitSet> cartesianProduct(List<Set<BitSet>> childrenTableMap) {
+ return Sets.cartesianProduct(childrenTableMap)
+ .stream()
+ .map(bitSetList -> {
+ BitSet bitSet = new BitSet();
+ for (BitSet b : bitSetList) {
+ bitSet.or(b);
+ }
+ return bitSet;
+ })
+ .collect(Collectors.toSet());
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/InitMaterializationContextHook.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/InitMaterializationContextHook.java
index baf714fe280..8046639d1ba 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/InitMaterializationContextHook.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/InitMaterializationContextHook.java
@@ -32,6 +32,7 @@ import
org.apache.doris.nereids.trees.plans.logical.LogicalProject;
import org.apache.doris.nereids.trees.plans.visitor.TableCollector;
import
org.apache.doris.nereids.trees.plans.visitor.TableCollector.TableCollectorContext;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@@ -56,7 +57,11 @@ public class InitMaterializationContextHook implements
PlannerHook {
initMaterializationContext(planner.getCascadesContext());
}
- private void initMaterializationContext(CascadesContext cascadesContext) {
+ /**
+ * init materialization context
+ */
+ @VisibleForTesting
+ public void initMaterializationContext(CascadesContext cascadesContext) {
if
(!cascadesContext.getConnectContext().getSessionVariable().isEnableMaterializedViewRewrite())
{
return;
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/memo/StructInfoMapTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/memo/StructInfoMapTest.java
new file mode 100644
index 00000000000..0699f04b92f
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/memo/StructInfoMapTest.java
@@ -0,0 +1,81 @@
+// 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.memo;
+
+import org.apache.doris.catalog.MTMV;
+import org.apache.doris.mtmv.MTMVRelationManager;
+import org.apache.doris.nereids.CascadesContext;
+import org.apache.doris.nereids.sqltest.SqlTestBase;
+import org.apache.doris.nereids.util.PlanChecker;
+import org.apache.doris.qe.ConnectContext;
+
+import mockit.Mock;
+import mockit.MockUp;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.BitSet;
+import java.util.Set;
+
+class StructInfoMapTest extends SqlTestBase {
+ @Test
+ void testTableMap() throws Exception {
+ CascadesContext c1 = createCascadesContext(
+ "select T1.id from T1 inner join T2 "
+ + "on T1.id = T2.id "
+ + "inner join T3 on T1.id = T3.id",
+ connectContext
+ );
+ PlanChecker.from(c1)
+ .analyze()
+ .rewrite()
+ .optimize();
+ Group root = c1.getMemo().getRoot();
+ Set<BitSet> tableMaps = root.getstructInfoMap().getTableMaps();
+ Assertions.assertTrue(tableMaps.isEmpty());
+ root.getstructInfoMap().refresh(root);
+ Assertions.assertEquals(1, tableMaps.size());
+ new MockUp<MTMVRelationManager>() {
+ @Mock
+ public boolean isMVPartitionValid(MTMV mtmv, ConnectContext ctx) {
+ return true;
+ }
+ };
+ connectContext.getSessionVariable().enableMaterializedViewRewrite =
true;
+ createMvByNereids("create materialized view mv1 BUILD IMMEDIATE
REFRESH COMPLETE ON MANUAL\n"
+ + " DISTRIBUTED BY RANDOM BUCKETS 1\n"
+ + " PROPERTIES ('replication_num' = '1') \n"
+ + " as select T1.id from T1 inner join T2 "
+ + "on T1.id = T2.id;");
+ c1 = createCascadesContext(
+ "select T1.id from T1 inner join T2 "
+ + "on T1.id = T2.id "
+ + "inner join T3 on T1.id = T3.id",
+ connectContext
+ );
+ PlanChecker.from(c1)
+ .analyze()
+ .rewrite()
+ .optimize()
+ .printlnBestPlanTree();
+ root = c1.getMemo().getRoot();
+ root.getstructInfoMap().refresh(root);
+ tableMaps = root.getstructInfoMap().getTableMaps();
+ Assertions.assertEquals(2, tableMaps.size());
+ }
+}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/PlanChecker.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/PlanChecker.java
index 0c6cc0e577e..9471e18f6a5 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/util/PlanChecker.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/util/PlanChecker.java
@@ -49,6 +49,7 @@ import org.apache.doris.nereids.rules.RuleFactory;
import org.apache.doris.nereids.rules.RuleSet;
import org.apache.doris.nereids.rules.RuleType;
import
org.apache.doris.nereids.rules.analysis.BindRelation.CustomTableResolver;
+import
org.apache.doris.nereids.rules.exploration.mv.InitMaterializationContextHook;
import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
import org.apache.doris.nereids.trees.plans.GroupPlan;
import org.apache.doris.nereids.trees.plans.Plan;
@@ -121,6 +122,7 @@ public class PlanChecker {
public PlanChecker analyze() {
this.cascadesContext.newAnalyzer().analyze();
this.cascadesContext.toMemo();
+
InitMaterializationContextHook.INSTANCE.initMaterializationContext(this.cascadesContext);
return this;
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
b/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
index 58b55f0a7b5..7de8a9a830b 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/utframe/TestWithFeService.java
@@ -58,6 +58,7 @@ import org.apache.doris.common.FeConstants;
import org.apache.doris.common.MetaNotFoundException;
import org.apache.doris.common.util.SqlParserUtils;
import org.apache.doris.datasource.CatalogIf;
+import org.apache.doris.job.base.AbstractJob;
import org.apache.doris.nereids.CascadesContext;
import org.apache.doris.nereids.StatementContext;
import org.apache.doris.nereids.glue.LogicalPlanAdapter;
@@ -65,10 +66,13 @@ import org.apache.doris.nereids.parser.NereidsParser;
import org.apache.doris.nereids.rules.RuleType;
import org.apache.doris.nereids.trees.expressions.StatementScopeIdGenerator;
import org.apache.doris.nereids.trees.plans.commands.AddConstraintCommand;
+import org.apache.doris.nereids.trees.plans.commands.CreateMTMVCommand;
import org.apache.doris.nereids.trees.plans.commands.CreateTableCommand;
import org.apache.doris.nereids.trees.plans.commands.DropConstraintCommand;
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
import org.apache.doris.nereids.util.MemoTestUtils;
+import org.apache.doris.persist.CreateTableInfo;
+import org.apache.doris.persist.EditLog;
import org.apache.doris.planner.Planner;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.DdlExecutor;
@@ -795,6 +799,30 @@ public abstract class TestWithFeService {
Thread.sleep(100);
}
+ protected void createMvByNereids(String sql) throws Exception {
+ new MockUp<EditLog>() {
+ @Mock
+ public void logCreateTable(CreateTableInfo info) {
+ System.out.println("skip log create table...");
+ }
+
+ @Mock
+ public void logCreateJob(AbstractJob job) {
+ System.out.println("skip log create job...");
+ }
+ };
+ NereidsParser nereidsParser = new NereidsParser();
+ LogicalPlan parsed = nereidsParser.parseSingle(sql);
+ StmtExecutor stmtExecutor = new StmtExecutor(connectContext, sql);
+ if (parsed instanceof CreateMTMVCommand) {
+ ((CreateMTMVCommand) parsed).run(connectContext, stmtExecutor);
+ }
+ checkAlterJob();
+ // waiting table state to normal
+ Thread.sleep(1000);
+
+ }
+
private void updateReplicaPathHash() {
com.google.common.collect.Table<Long, Long, Replica> replicaMetaTable
= Env.getCurrentInvertedIndex()
.getReplicaMetaTable();
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]