This is an automated email from the ASF dual-hosted git repository.

yiguolei pushed a commit to branch branch-2.1
in repository https://gitbox.apache.org/repos/asf/doris.git

commit 5046fa2bea46e08154b56f066642677ab2de96b4
Author: seawinde <149132972+seawi...@users.noreply.github.com>
AuthorDate: Sat May 11 11:04:38 2024 +0800

    [improvement](mtmv) Split the expression mapping in 
LogicalCompatibilityContext for performance (#34646)
    
    Need query to view expression mapping when check the logic of hyper graph 
is equals or not.
    Getting all expression mapping one-time may affect performance. So split 
the expresson to three type
    JOIN_EDGE, NODE, FILTER_EDGE and get them step by step.
---
 .../rules/exploration/mv/HyperGraphComparator.java |  6 +-
 .../mv/LogicalCompatibilityContext.java            | 97 ++++++++++++++++++----
 .../nereids/rules/exploration/mv/StructInfo.java   | 64 ++++++++++----
 3 files changed, 132 insertions(+), 35 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparator.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparator.java
index 956a974982c..0c9dc9c33de 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparator.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/HyperGraphComparator.java
@@ -238,7 +238,7 @@ public class HyperGraphComparator {
         int size = queryExprSetList.size();
         for (int i = 0; i < size; i++) {
             Set<Expression> mappingQueryExprSet = 
queryExprSetList.get(i).stream()
-                    .map(e -> 
logicalCompatibilityContext.getQueryToViewEdgeExpressionMapping().get(e))
+                    .map(e -> 
logicalCompatibilityContext.getQueryToViewAllExpressionMapping().get(e))
                     .collect(Collectors.toSet());
             if (!mappingQueryExprSet.equals(viewExprSetList.get(i))) {
                 return false;
@@ -391,7 +391,7 @@ public class HyperGraphComparator {
     }
 
     private Map<Expression, Expression> getQueryToViewExprMap() {
-        return 
logicalCompatibilityContext.getQueryToViewEdgeExpressionMapping();
+        return 
logicalCompatibilityContext.getQueryToViewAllExpressionMapping();
     }
 
     private Map<Integer, Integer> getQueryToViewNodeIdMap() {
@@ -414,7 +414,7 @@ public class HyperGraphComparator {
     }
 
     private Expression getViewExprFromQueryExpr(Expression query) {
-        return 
logicalCompatibilityContext.getQueryToViewEdgeExpressionMapping().get(query);
+        return 
logicalCompatibilityContext.getQueryToViewAllExpressionMapping().get(query);
     }
 
     private void refreshViewEdges() {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/LogicalCompatibilityContext.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/LogicalCompatibilityContext.java
index 7f92735da64..b4ed509f300 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/LogicalCompatibilityContext.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/LogicalCompatibilityContext.java
@@ -19,6 +19,7 @@ package org.apache.doris.nereids.rules.exploration.mv;
 
 import org.apache.doris.nereids.jobs.joinorder.hypergraph.node.StructInfoNode;
 import org.apache.doris.nereids.memo.GroupExpression;
+import 
org.apache.doris.nereids.rules.exploration.mv.StructInfo.ExpressionPosition;
 import 
org.apache.doris.nereids.rules.exploration.mv.mapping.Mapping.MappedRelation;
 import org.apache.doris.nereids.rules.exploration.mv.mapping.RelationMapping;
 import org.apache.doris.nereids.rules.exploration.mv.mapping.SlotMapping;
@@ -32,33 +33,55 @@ import org.apache.doris.nereids.trees.plans.RelationId;
 import org.apache.doris.nereids.util.ExpressionUtils;
 import org.apache.doris.nereids.util.Utils;
 
+import com.google.common.base.Suppliers;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.Supplier;
 
 /**
  * For outer join we should check the outer join compatibility between query 
and view
  */
 public class LogicalCompatibilityContext {
     private final BiMap<StructInfoNode, StructInfoNode> queryToViewNodeMapping;
-    private final BiMap<Expression, Expression> 
queryToViewEdgeExpressionMapping;
     private final BiMap<Integer, Integer> queryToViewNodeIDMapping;
     private final ObjectId planNodeId;
+    private final Supplier<BiMap<Expression, Expression>> 
queryToViewJoinEdgeExpressionMappingSupplier;
+    private final Supplier<BiMap<Expression, Expression>> 
queryToViewNodeExpressionMappingSupplier;
+    private final Supplier<BiMap<Expression, Expression>> 
queryToViewFilterEdgeExpressionMappingSupplier;
+    @Deprecated
+    private BiMap<Expression, Expression> queryToViewAllExpressionMapping;
 
     /**
      * LogicalCompatibilityContext
      */
-    public LogicalCompatibilityContext(BiMap<StructInfoNode, StructInfoNode> 
queryToViewNodeMapping,
-            BiMap<Expression, Expression> queryToViewEdgeExpressionMapping,
-            StructInfo queryStructInfo) {
+    private LogicalCompatibilityContext(BiMap<StructInfoNode, StructInfoNode> 
queryToViewNodeMapping,
+            Map<SlotReference, SlotReference> viewToQuerySlotMapping, 
StructInfo queryStructInfo,
+            StructInfo viewStructInfo) {
+
+        this.queryToViewJoinEdgeExpressionMappingSupplier =
+                Suppliers.memoize(() -> 
generateExpressionMapping(viewToQuerySlotMapping,
+                        
queryStructInfo.getShuttledExpressionsToExpressionsMap().get(ExpressionPosition.JOIN_EDGE),
+                        
viewStructInfo.getShuttledExpressionsToExpressionsMap().get(ExpressionPosition.JOIN_EDGE)));
+
+        this.queryToViewNodeExpressionMappingSupplier =
+                Suppliers.memoize(() -> 
generateExpressionMapping(viewToQuerySlotMapping,
+                        
queryStructInfo.getShuttledExpressionsToExpressionsMap().get(ExpressionPosition.NODE),
+                        
viewStructInfo.getShuttledExpressionsToExpressionsMap().get(ExpressionPosition.NODE)));
+
+        this.queryToViewFilterEdgeExpressionMappingSupplier =
+                Suppliers.memoize(() -> 
generateExpressionMapping(viewToQuerySlotMapping,
+                        
queryStructInfo.getShuttledExpressionsToExpressionsMap().get(ExpressionPosition.FILTER_EDGE),
+                        
viewStructInfo.getShuttledExpressionsToExpressionsMap().get(ExpressionPosition.FILTER_EDGE)));
+
         this.queryToViewNodeMapping = queryToViewNodeMapping;
-        this.queryToViewEdgeExpressionMapping = 
queryToViewEdgeExpressionMapping;
         this.queryToViewNodeIDMapping = HashBiMap.create();
+        queryToViewNodeMapping.forEach((k, v) -> 
queryToViewNodeIDMapping.put(k.getIndex(), v.getIndex()));
+
         this.planNodeId = queryStructInfo.getTopPlan().getGroupExpression()
                 .map(GroupExpression::getId).orElseGet(() -> new ObjectId(-1));
-        queryToViewNodeMapping.forEach((k, v) -> 
queryToViewNodeIDMapping.put(k.getIndex(), v.getIndex()));
     }
 
     public BiMap<StructInfoNode, StructInfoNode> getQueryToViewNodeMapping() {
@@ -69,8 +92,31 @@ public class LogicalCompatibilityContext {
         return queryToViewNodeIDMapping;
     }
 
-    public BiMap<Expression, Expression> getQueryToViewEdgeExpressionMapping() 
{
-        return queryToViewEdgeExpressionMapping;
+    /**
+     * Get all expression mapping in query to view
+     */
+    @Deprecated
+    public BiMap<Expression, Expression> getQueryToViewAllExpressionMapping() {
+        if (queryToViewAllExpressionMapping != null) {
+            return queryToViewAllExpressionMapping;
+        }
+        queryToViewAllExpressionMapping = HashBiMap.create();
+        
queryToViewAllExpressionMapping.putAll(getQueryToViewJoinEdgeExpressionMapping());
+        
queryToViewAllExpressionMapping.putAll(getQueryToViewNodeExpressionMapping());
+        
queryToViewAllExpressionMapping.putAll(getQueryToViewFilterEdgeExpressionMapping());
+        return queryToViewAllExpressionMapping;
+    }
+
+    public BiMap<Expression, Expression> 
getQueryToViewJoinEdgeExpressionMapping() {
+        return queryToViewJoinEdgeExpressionMappingSupplier.get();
+    }
+
+    public BiMap<Expression, Expression> getQueryToViewNodeExpressionMapping() 
{
+        return queryToViewNodeExpressionMappingSupplier.get();
+    }
+
+    public BiMap<Expression, Expression> 
getQueryToViewFilterEdgeExpressionMapping() {
+        return queryToViewFilterEdgeExpressionMappingSupplier.get();
     }
 
     public ObjectId getPlanNodeId() {
@@ -104,24 +150,33 @@ public class LogicalCompatibilityContext {
         // init expression mapping
         Map<SlotReference, SlotReference> viewToQuerySlotMapping = 
queryToViewSlotMapping.inverse()
                 .toSlotReferenceMap();
-        Map<Expression, Expression> queryShuttledExprToExprMap =
-                queryStructInfo.getShuttledHashConjunctsToConjunctsMap();
-        Map<Expression, Expression> viewShuttledExprToExprMap =
-                viewStructInfo.getShuttledHashConjunctsToConjunctsMap();
+        return new LogicalCompatibilityContext(queryToViewNodeMapping,
+                viewToQuerySlotMapping,
+                queryStructInfo,
+                viewStructInfo);
+    }
+
+    private static BiMap<Expression, Expression> generateExpressionMapping(
+            Map<SlotReference, SlotReference> viewToQuerySlotMapping,
+            Map<Expression, Expression> queryShuttledExprToExprMap,
+            Map<Expression, Expression> viewShuttledExprToExprMap) {
         final Map<Expression, Expression> viewEdgeToConjunctsMapQueryBased = 
new HashMap<>();
+        BiMap<Expression, Expression> queryToViewEdgeMapping = 
HashBiMap.create();
+        if (queryShuttledExprToExprMap == null || viewShuttledExprToExprMap == 
null
+                || queryShuttledExprToExprMap.isEmpty() || 
viewShuttledExprToExprMap.isEmpty()) {
+            return queryToViewEdgeMapping;
+        }
         viewShuttledExprToExprMap.forEach((shuttledExpr, expr) -> {
             viewEdgeToConjunctsMapQueryBased.put(
-                    orderSlotAsc(ExpressionUtils.replace(shuttledExpr, 
viewToQuerySlotMapping)),
-                    expr);
+                    orderSlotAsc(ExpressionUtils.replace(shuttledExpr, 
viewToQuerySlotMapping)), expr);
         });
-        BiMap<Expression, Expression> queryToViewEdgeMapping = 
HashBiMap.create();
         queryShuttledExprToExprMap.forEach((exprSet, edge) -> {
             Expression viewExpr = 
viewEdgeToConjunctsMapQueryBased.get(orderSlotAsc(exprSet));
             if (viewExpr != null) {
                 queryToViewEdgeMapping.put(edge, viewExpr);
             }
         });
-        return new LogicalCompatibilityContext(queryToViewNodeMapping, 
queryToViewEdgeMapping, queryStructInfo);
+        return queryToViewEdgeMapping;
     }
 
     private static Expression orderSlotAsc(Expression expression) {
@@ -151,6 +206,14 @@ public class LogicalCompatibilityContext {
     public String toString() {
         return Utils.toSqlString("LogicalCompatibilityContext",
                 "queryToViewNodeMapping", queryToViewNodeMapping.toString(),
-                "queryToViewEdgeExpressionMapping", 
queryToViewEdgeExpressionMapping.toString());
+                "queryToViewJoinEdgeExpressionMapping",
+                queryToViewJoinEdgeExpressionMappingSupplier.get() == null
+                        ? "" : 
queryToViewJoinEdgeExpressionMappingSupplier.get().toString(),
+                "queryToViewNodeExpressionMapping",
+                queryToViewNodeExpressionMappingSupplier.get() == null
+                        ? "" : 
queryToViewNodeExpressionMappingSupplier.get().toString(),
+                "queryToViewFilterEdgeExpressionMapping",
+                queryToViewFilterEdgeExpressionMappingSupplier.get() == null
+                        ? "" : 
queryToViewFilterEdgeExpressionMappingSupplier.get().toString());
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/StructInfo.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/StructInfo.java
index b617cdfe701..7f6b5f0d291 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/StructInfo.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/StructInfo.java
@@ -106,7 +106,7 @@ public class StructInfo {
     private final EquivalenceClass equivalenceClass;
     // Key is the expression shuttled and the value is the origin expression
     // this is for building LogicalCompatibilityContext later.
-    private final Map<Expression, Expression> 
shuttledHashConjunctsToConjunctsMap;
+    private final Map<ExpressionPosition, Map<Expression, Expression>> 
shuttledExpressionsToExpressionsMap;
     // Record the exprId and the corresponding expr map, this is used by 
expression shuttled
     private final Map<ExprId, Expression> namedExprIdAndExprMapping;
 
@@ -117,7 +117,7 @@ public class StructInfo {
             Plan bottomPlan, List<CatalogRelation> relations,
             Map<RelationId, StructInfoNode> relationIdStructInfoNodeMap,
             @Nullable Predicates predicates,
-            Map<Expression, Expression> shuttledHashConjunctsToConjunctsMap,
+            Map<ExpressionPosition, Map<Expression, Expression>> 
shuttledExpressionsToExpressionsMap,
             Map<ExprId, Expression> namedExprIdAndExprMapping) {
         this.originalPlan = originalPlan;
         this.originalPlanId = originalPlanId;
@@ -140,7 +140,7 @@ public class StructInfo {
                 predicatesDerive(this.predicates, topPlan, tableBitSet);
         this.splitPredicate = derivedPredicates.key();
         this.equivalenceClass = derivedPredicates.value();
-        this.shuttledHashConjunctsToConjunctsMap = 
shuttledHashConjunctsToConjunctsMap;
+        this.shuttledExpressionsToExpressionsMap = 
shuttledExpressionsToExpressionsMap;
         this.namedExprIdAndExprMapping = namedExprIdAndExprMapping;
     }
 
@@ -150,12 +150,12 @@ public class StructInfo {
     public StructInfo withPredicates(Predicates predicates) {
         return new StructInfo(this.originalPlan, this.originalPlanId, 
this.hyperGraph, this.valid, this.topPlan,
                 this.bottomPlan, this.relations, 
this.relationIdStructInfoNodeMap, predicates,
-                this.shuttledHashConjunctsToConjunctsMap, 
this.namedExprIdAndExprMapping);
+                this.shuttledExpressionsToExpressionsMap, 
this.namedExprIdAndExprMapping);
     }
 
     private static boolean collectStructInfoFromGraph(HyperGraph hyperGraph,
             Plan topPlan,
-            Map<Expression, Expression> shuttledHashConjunctsToConjunctsMap,
+            Map<ExpressionPosition, Map<Expression, Expression>> 
shuttledExpressionsToExpressionsMap,
             Map<ExprId, Expression> namedExprIdAndExprMapping,
             List<CatalogRelation> relations,
             Map<RelationId, StructInfoNode> relationIdStructInfoNodeMap) {
@@ -189,7 +189,8 @@ public class StructInfo {
                 topPlan.accept(ExpressionLineageReplacer.INSTANCE, 
replaceContext);
                 // Replace expressions by expression map
                 List<Expression> replacedExpressions = 
replaceContext.getReplacedExpressions();
-                
shuttledHashConjunctsToConjunctsMap.put(replacedExpressions.get(0), 
conjunctExpr);
+                
putShuttledExpressionsToExpressionsMap(shuttledExpressionsToExpressionsMap,
+                        ExpressionPosition.JOIN_EDGE, 
replacedExpressions.get(0), conjunctExpr);
                 // Record this, will be used in top level expression shuttle 
later, see the method
                 // ExpressionLineageReplacer#visitGroupPlan
                 
namedExprIdAndExprMapping.putAll(replaceContext.getExprIdExpressionMap());
@@ -213,7 +214,8 @@ public class StructInfo {
                     
structInfoNode.getPlan().accept(ExpressionLineageReplacer.INSTANCE, 
replaceContext);
                     // Replace expressions by expression map
                     List<Expression> replacedExpressions = 
replaceContext.getReplacedExpressions();
-                    
shuttledHashConjunctsToConjunctsMap.put(replacedExpressions.get(0), expression);
+                    
putShuttledExpressionsToExpressionsMap(shuttledExpressionsToExpressionsMap,
+                            ExpressionPosition.NODE, 
replacedExpressions.get(0), expression);
                     // Record this, will be used in top level expression 
shuttle later, see the method
                     // ExpressionLineageReplacer#visitGroupPlan
                     
namedExprIdAndExprMapping.putAll(replaceContext.getExprIdExpressionMap());
@@ -226,8 +228,10 @@ public class StructInfo {
             filterExpressions.forEach(predicate -> {
                 // this is used for LogicalCompatibilityContext
                 ExpressionUtils.extractConjunction(predicate).forEach(expr ->
-                        
shuttledHashConjunctsToConjunctsMap.put(ExpressionUtils.shuttleExpressionWithLineage(
-                                predicate, topPlan, hyperTableBitSet), 
predicate));
+                        
putShuttledExpressionsToExpressionsMap(shuttledExpressionsToExpressionsMap,
+                                ExpressionPosition.FILTER_EDGE,
+                                
ExpressionUtils.shuttleExpressionWithLineage(predicate, topPlan, 
hyperTableBitSet),
+                                predicate));
             });
         });
         return true;
@@ -299,7 +303,8 @@ public class StructInfo {
         // collect struct info fromGraph
         List<CatalogRelation> relationList = new ArrayList<>();
         Map<RelationId, StructInfoNode> relationIdStructInfoNodeMap = new 
LinkedHashMap<>();
-        Map<Expression, Expression> shuttledHashConjunctsToConjunctsMap = new 
LinkedHashMap<>();
+        Map<ExpressionPosition, Map<Expression, Expression>> 
shuttledHashConjunctsToConjunctsMap =
+                new LinkedHashMap<>();
         Map<ExprId, Expression> namedExprIdAndExprMapping = new 
LinkedHashMap<>();
         boolean valid = collectStructInfoFromGraph(hyperGraph, topPlan, 
shuttledHashConjunctsToConjunctsMap,
                 namedExprIdAndExprMapping,
@@ -359,8 +364,21 @@ public class StructInfo {
         return relationIdStructInfoNodeMap;
     }
 
-    public Map<Expression, Expression> 
getShuttledHashConjunctsToConjunctsMap() {
-        return shuttledHashConjunctsToConjunctsMap;
+    public Map<ExpressionPosition, Map<Expression, Expression>> 
getShuttledExpressionsToExpressionsMap() {
+        return shuttledExpressionsToExpressionsMap;
+    }
+
+    private static void putShuttledExpressionsToExpressionsMap(
+            Map<ExpressionPosition, Map<Expression, Expression>> 
shuttledExpressionsToExpressionsMap,
+            ExpressionPosition expressionPosition,
+            Expression key, Expression value) {
+        Map<Expression, Expression> expressionExpressionMap = 
shuttledExpressionsToExpressionsMap.get(
+                expressionPosition);
+        if (expressionExpressionMap == null) {
+            expressionExpressionMap = new LinkedHashMap<>();
+            shuttledExpressionsToExpressionsMap.put(expressionPosition, 
expressionExpressionMap);
+        }
+        expressionExpressionMap.put(key, value);
     }
 
     public List<? extends Expression> getExpressions() {
@@ -444,7 +462,9 @@ public class StructInfo {
         }
     }
 
-    /** Judge if source contains all target */
+    /**
+     * Judge if source contains all target
+     */
     public static boolean containsAll(BitSet source, BitSet target) {
         if (source.size() < target.size()) {
             return false;
@@ -624,7 +644,9 @@ public class StructInfo {
         }
     }
 
-    /**Collect partitions which scan used according to given table */
+    /**
+     * Collect partitions which scan used according to given table
+     */
     public static class QueryScanPartitionsCollector extends 
DefaultPlanVisitor<Plan, Map<Long, Set<PartitionItem>>> {
         @Override
         public Plan visitLogicalCatalogRelation(LogicalCatalogRelation 
catalogRelation,
@@ -648,7 +670,9 @@ public class StructInfo {
         }
     }
 
-    /**Add filter on table scan according to table filter map */
+    /**
+     * Add filter on table scan according to table filter map
+     */
     public static Plan addFilterOnTableScan(Plan queryPlan, Map<TableIf, 
Set<Expression>> filterOnOriginPlan,
             CascadesContext parentCascadesContext) {
         // Firstly, construct filter form invalid partition, this filter 
should be added on origin plan
@@ -663,4 +687,14 @@ public class StructInfo {
             return context.getRewritePlan();
         }, queryPlanWithUnionFilter, queryPlan);
     }
+
+    /**
+     * Expressions may appear in three place in hype graph, this identifies 
the position where
+     * expression appear in hyper graph
+     */
+    public static enum ExpressionPosition {
+        JOIN_EDGE,
+        NODE,
+        FILTER_EDGE
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to