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

morrysnow 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 8d5eabb64f [enhancement](Nereids) reduce CostAndEnforcerJob call times 
(#14442)
8d5eabb64f is described below

commit 8d5eabb64ffe90097101e16d8ce51e4a5cf69e27
Author: morrySnow <[email protected]>
AuthorDate: Wed Nov 23 16:57:41 2022 +0800

    [enhancement](Nereids) reduce CostAndEnforcerJob call times (#14442)
    
    record pruned plan's cost to avoid optimize same GroupExpression more than 
once.
---
 .../java/org/apache/doris/nereids/PlanContext.java |  15 +-
 .../apache/doris/nereids/cost/CostCalculator.java  |  15 +-
 .../java/org/apache/doris/nereids/jobs/Job.java    |   3 +-
 .../nereids/jobs/cascades/CostAndEnforcerJob.java  |   3 +-
 .../java/org/apache/doris/nereids/memo/Group.java  | 226 ++++++++++-----------
 .../nereids/properties/RequestPropertyDeriver.java |  29 ++-
 .../apache/doris/statistics/StatsDeriveResult.java |   9 +-
 .../properties/RequestPropertyDeriverTest.java     |   2 +-
 8 files changed, 143 insertions(+), 159 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/PlanContext.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/PlanContext.java
index 8b45a746af..6ad6327291 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/PlanContext.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/PlanContext.java
@@ -18,7 +18,6 @@
 package org.apache.doris.nereids;
 
 import org.apache.doris.common.Id;
-import org.apache.doris.nereids.memo.Group;
 import org.apache.doris.nereids.memo.GroupExpression;
 import org.apache.doris.nereids.properties.LogicalProperties;
 import org.apache.doris.nereids.trees.expressions.Slot;
@@ -26,7 +25,6 @@ import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.statistics.StatsDeriveResult;
 
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
 
 import java.util.List;
 
@@ -37,8 +35,6 @@ import java.util.List;
  * Inspired by GPORCA-CExpressionHandle.
  */
 public class PlanContext {
-    // array of children's derived stats
-    private final List<StatsDeriveResult> childrenStats;
     // attached group expression
     private final GroupExpression groupExpression;
 
@@ -47,21 +43,12 @@ public class PlanContext {
      */
     public PlanContext(GroupExpression groupExpression) {
         this.groupExpression = groupExpression;
-        childrenStats = 
Lists.newArrayListWithCapacity(groupExpression.children().size());
-
-        for (Group group : groupExpression.children()) {
-            childrenStats.add(group.getStatistics());
-        }
     }
 
     public GroupExpression getGroupExpression() {
         return groupExpression;
     }
 
-    public List<StatsDeriveResult> getChildrenStats() {
-        return childrenStats;
-    }
-
     public StatsDeriveResult getStatisticsWithCheck() {
         StatsDeriveResult statistics = 
groupExpression.getOwnerGroup().getStatistics();
         Preconditions.checkNotNull(statistics);
@@ -84,7 +71,7 @@ public class PlanContext {
      * Get child statistics.
      */
     public StatsDeriveResult getChildStatistics(int index) {
-        StatsDeriveResult statistics = childrenStats.get(index);
+        StatsDeriveResult statistics = 
groupExpression.child(index).getStatistics();
         Preconditions.checkNotNull(statistics);
         return statistics;
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/cost/CostCalculator.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/cost/CostCalculator.java
index a0ffd98703..83f2549f41 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/cost/CostCalculator.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/cost/CostCalculator.java
@@ -17,7 +17,6 @@
 
 package org.apache.doris.nereids.cost;
 
-import org.apache.doris.common.Id;
 import org.apache.doris.nereids.PlanContext;
 import org.apache.doris.nereids.memo.GroupExpression;
 import org.apache.doris.nereids.properties.DistributionSpec;
@@ -41,8 +40,6 @@ import org.apache.doris.statistics.StatsDeriveResult;
 
 import com.google.common.base.Preconditions;
 
-import java.util.List;
-
 /**
  * Calculate the cost of a plan.
  * Inspired by Presto.
@@ -187,25 +184,22 @@ public class CostCalculator {
 
             StatsDeriveResult statistics = context.getStatisticsWithCheck();
             StatsDeriveResult inputStatistics = context.getChildStatistics(0);
-            return CostEstimate.of(inputStatistics.computeSize(), 
statistics.computeSize(), 0);
+            return CostEstimate.of(inputStatistics.getRowCount(), 
statistics.computeSize(), 0);
         }
 
         @Override
         public CostEstimate visitPhysicalHashJoin(
                 PhysicalHashJoin<? extends Plan, ? extends Plan> 
physicalHashJoin, PlanContext context) {
             Preconditions.checkState(context.getGroupExpression().arity() == 
2);
-            Preconditions.checkState(context.getChildrenStats().size() == 2);
 
             StatsDeriveResult outputStats = 
physicalHashJoin.getGroupExpression().get().getOwnerGroup().getStatistics();
-            double outputRowCount = outputStats.computeSize();
+            double outputRowCount = outputStats.getRowCount();
 
             StatsDeriveResult probeStats = context.getChildStatistics(0);
             StatsDeriveResult buildStats = context.getChildStatistics(1);
-            List<Id> leftIds = context.getChildOutputIds(0);
-            List<Id> rightIds = context.getChildOutputIds(1);
 
-            double leftRowCount = probeStats.computeColumnSize(leftIds);
-            double rightRowCount = buildStats.computeColumnSize(rightIds);
+            double leftRowCount = probeStats.getRowCount();
+            double rightRowCount = buildStats.getRowCount();
             /*
             pattern1: L join1 (Agg1() join2 Agg2())
             result number of join2 may much less than Agg1.
@@ -240,7 +234,6 @@ public class CostCalculator {
                 PlanContext context) {
             // TODO: copy from physicalHashJoin, should update according to 
physical nested loop join properties.
             Preconditions.checkState(context.getGroupExpression().arity() == 
2);
-            Preconditions.checkState(context.getChildrenStats().size() == 2);
 
             StatsDeriveResult leftStatistics = context.getChildStatistics(0);
             StatsDeriveResult rightStatistics = context.getChildStatistics(1);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/Job.java 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/Job.java
index 4459babb2b..7d200cd659 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/Job.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/Job.java
@@ -80,8 +80,7 @@ public abstract class Job {
      * @param candidateRules rules to be applied
      * @return all rules that can be applied on this group expression
      */
-    public List<Rule> getValidRules(GroupExpression groupExpression,
-            List<Rule> candidateRules) {
+    public List<Rule> getValidRules(GroupExpression groupExpression, 
List<Rule> candidateRules) {
         return candidateRules.stream()
                 .filter(rule -> Objects.nonNull(rule) && 
rule.getPattern().matchRoot(groupExpression.getPlan())
                         && 
groupExpression.notApplied(rule)).collect(Collectors.toList());
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/CostAndEnforcerJob.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/CostAndEnforcerJob.java
index bb36e719c4..f684e9430d 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/CostAndEnforcerJob.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/CostAndEnforcerJob.java
@@ -41,6 +41,7 @@ import java.util.Optional;
  * Inspired by NoisePage and ORCA-Paper.
  */
 public class CostAndEnforcerJob extends Job implements Cloneable {
+
     // GroupExpression to optimize
     private final GroupExpression groupExpression;
 
@@ -165,7 +166,7 @@ public class CostAndEnforcerJob extends Job implements 
Cloneable {
 
                 curTotalCost += 
lowestCostExpr.getLowestCostTable().get(requestChildProperty).first;
                 if (curTotalCost > context.getCostUpperBound()) {
-                    break;
+                    curTotalCost = Double.POSITIVE_INFINITY;
                 }
                 // the request child properties will be covered by the output 
properties
                 // that corresponding to the request properties. so if we run 
a costAndEnforceJob of the same
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 686be94c72..e699e74eb3 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
@@ -53,7 +53,7 @@ public class Group {
     // Map of cost lower bounds
     // Map required plan props to cost lower bound of corresponding plan
     private final Map<PhysicalProperties, Pair<Double, GroupExpression>> 
lowestCostPlans = Maps.newHashMap();
-    private double costLowerBound = -1;
+
     private boolean isExplored = false;
 
     private StatsDeriveResult statistics;
@@ -101,6 +101,37 @@ public class Group {
         return groupExpression;
     }
 
+    public void addLogicalExpression(GroupExpression groupExpression) {
+        groupExpression.setOwnerGroup(this);
+        logicalExpressions.add(groupExpression);
+    }
+
+    public List<GroupExpression> getLogicalExpressions() {
+        return logicalExpressions;
+    }
+
+    public GroupExpression logicalExpressionsAt(int index) {
+        return logicalExpressions.get(index);
+    }
+
+    /**
+     * Get the first logical group expression in this group.
+     * If there is no logical group expression or more than one, throw an 
exception.
+     *
+     * @return the first logical group expression in this group
+     */
+    public GroupExpression getLogicalExpression() {
+        Preconditions.checkArgument(logicalExpressions.size() == 1,
+                "There should be only one Logical Expression in Group");
+        Preconditions.checkArgument(physicalExpressions.isEmpty(),
+                "The Physical Expression list in Group should be empty");
+        return logicalExpressions.get(0);
+    }
+
+    public List<GroupExpression> getPhysicalExpressions() {
+        return physicalExpressions;
+    }
+
     /**
      * Remove groupExpression from this group.
      *
@@ -117,11 +148,6 @@ public class Group {
         return groupExpression;
     }
 
-    public void addLogicalExpression(GroupExpression groupExpression) {
-        groupExpression.setOwnerGroup(this);
-        logicalExpressions.add(groupExpression);
-    }
-
     public List<GroupExpression> clearLogicalExpressions() {
         List<GroupExpression> move = logicalExpressions.stream()
                 .peek(groupExpr -> groupExpr.setOwnerGroup(null))
@@ -139,7 +165,28 @@ public class Group {
     }
 
     public double getCostLowerBound() {
-        return costLowerBound;
+        return -1D;
+    }
+
+    /**
+     * Get the lowest cost {@link 
org.apache.doris.nereids.trees.plans.physical.PhysicalPlan}
+     * which meeting the physical property constraints in this Group.
+     *
+     * @param physicalProperties the physical property constraints
+     * @return {@link Optional} of cost and {@link GroupExpression} of 
physical plan pair.
+     */
+    public Optional<Pair<Double, GroupExpression>> 
getLowestCostPlan(PhysicalProperties physicalProperties) {
+        if (physicalProperties == null || lowestCostPlans.isEmpty()) {
+            return Optional.empty();
+        }
+        return Optional.ofNullable(lowestCostPlans.get(physicalProperties));
+    }
+
+    public GroupExpression getBestPlan(PhysicalProperties properties) {
+        if (lowestCostPlans.containsKey(properties)) {
+            return lowestCostPlans.get(properties).second;
+        }
+        return null;
     }
 
     /**
@@ -155,13 +202,6 @@ public class Group {
         }
     }
 
-    public GroupExpression getBestPlan(PhysicalProperties properties) {
-        if (lowestCostPlans.containsKey(properties)) {
-            return lowestCostPlans.get(properties).second;
-        }
-        return null;
-    }
-
     /**
      * replace best plan with new properties
      */
@@ -182,32 +222,6 @@ public class Group {
         this.statistics = statistics;
     }
 
-    public List<GroupExpression> getLogicalExpressions() {
-        return logicalExpressions;
-    }
-
-    public GroupExpression logicalExpressionsAt(int index) {
-        return logicalExpressions.get(index);
-    }
-
-    /**
-     * Get the first logical group expression in this group.
-     * If there is no logical group expression or more than one, throw an 
exception.
-     *
-     * @return the first logical group expression in this group
-     */
-    public GroupExpression getLogicalExpression() {
-        Preconditions.checkArgument(logicalExpressions.size() == 1,
-                "There should be only one Logical Expression in Group");
-        Preconditions.checkArgument(physicalExpressions.isEmpty(),
-                "The Physical Expression list in Group should be empty");
-        return logicalExpressions.get(0);
-    }
-
-    public List<GroupExpression> getPhysicalExpressions() {
-        return physicalExpressions;
-    }
-
     public LogicalProperties getLogicalProperties() {
         return logicalProperties;
     }
@@ -224,20 +238,6 @@ public class Group {
         isExplored = explored;
     }
 
-    /**
-     * Get the lowest cost {@link 
org.apache.doris.nereids.trees.plans.physical.PhysicalPlan}
-     * which meeting the physical property constraints in this Group.
-     *
-     * @param physicalProperties the physical property constraints
-     * @return {@link Optional} of cost and {@link GroupExpression} of 
physical plan pair.
-     */
-    public Optional<Pair<Double, GroupExpression>> 
getLowestCostPlan(PhysicalProperties physicalProperties) {
-        if (physicalProperties == null || lowestCostPlans.isEmpty()) {
-            return Optional.empty();
-        }
-        return Optional.ofNullable(lowestCostPlans.get(physicalProperties));
-    }
-
     public List<GroupExpression> getParentGroupExpressions() {
         return ImmutableList.copyOf(parentExpressions.keySet());
     }
@@ -257,6 +257,65 @@ public class Group {
         return parentExpressions.size();
     }
 
+    /**
+     * move the ownerGroup of all logical expressions to target group
+     * if this.equals(target), do nothing.
+     *
+     * @param target the new owner group of expressions
+     */
+    public void moveLogicalExpressionOwnership(Group target) {
+        if (equals(target)) {
+            return;
+        }
+        for (GroupExpression expression : logicalExpressions) {
+            target.addGroupExpression(expression);
+        }
+        logicalExpressions.clear();
+    }
+
+    /**
+     * move the ownerGroup of all physical expressions to target group
+     * if this.equals(target), do nothing.
+     *
+     * @param target the new owner group of expressions
+     */
+    public void movePhysicalExpressionOwnership(Group target) {
+        if (equals(target)) {
+            return;
+        }
+        for (GroupExpression expression : physicalExpressions) {
+            target.addGroupExpression(expression);
+        }
+        physicalExpressions.clear();
+    }
+
+    /**
+     * move the ownerGroup of all lowestCostPlans to target group
+     * if this.equals(target), do nothing.
+     *
+     * @param target the new owner group of expressions
+     */
+    public void moveLowestCostPlansOwnership(Group target) {
+        if (equals(target)) {
+            return;
+        }
+        lowestCostPlans.forEach((physicalProperties, costAndGroupExpr) -> {
+            GroupExpression bestGroupExpression = costAndGroupExpr.second;
+            // change into target group.
+            if (bestGroupExpression.getOwnerGroup() == this || 
bestGroupExpression.getOwnerGroup() == null) {
+                bestGroupExpression.setOwnerGroup(target);
+            }
+            if (!target.lowestCostPlans.containsKey(physicalProperties)) {
+                target.lowestCostPlans.put(physicalProperties, 
costAndGroupExpr);
+            } else {
+                if (costAndGroupExpr.first < 
target.lowestCostPlans.get(physicalProperties).first) {
+                    target.lowestCostPlans.put(physicalProperties, 
costAndGroupExpr);
+                }
+            }
+        });
+        lowestCostPlans.clear();
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
@@ -322,63 +381,4 @@ public class Group {
         };
         return TreeStringUtils.treeString(this, toString, getChildren);
     }
-
-    /**
-     * move the ownerGroup of all logical expressions to target group
-     * if this.equals(target), do nothing.
-     *
-     * @param target the new owner group of expressions
-     */
-    public void moveLogicalExpressionOwnership(Group target) {
-        if (equals(target)) {
-            return;
-        }
-        for (GroupExpression expression : logicalExpressions) {
-            target.addGroupExpression(expression);
-        }
-        logicalExpressions.clear();
-    }
-
-    /**
-     * move the ownerGroup of all physical expressions to target group
-     * if this.equals(target), do nothing.
-     *
-     * @param target the new owner group of expressions
-     */
-    public void movePhysicalExpressionOwnership(Group target) {
-        if (equals(target)) {
-            return;
-        }
-        for (GroupExpression expression : physicalExpressions) {
-            target.addGroupExpression(expression);
-        }
-        physicalExpressions.clear();
-    }
-
-    /**
-     * move the ownerGroup of all lowestCostPlans to target group
-     * if this.equals(target), do nothing.
-     *
-     * @param target the new owner group of expressions
-     */
-    public void moveLowestCostPlansOwnership(Group target) {
-        if (equals(target)) {
-            return;
-        }
-        lowestCostPlans.forEach((physicalProperties, costAndGroupExpr) -> {
-            GroupExpression bestGroupExpression = costAndGroupExpr.second;
-            // change into target group.
-            if (bestGroupExpression.getOwnerGroup() == this || 
bestGroupExpression.getOwnerGroup() == null) {
-                bestGroupExpression.setOwnerGroup(target);
-            }
-            if (!target.lowestCostPlans.containsKey(physicalProperties)) {
-                target.lowestCostPlans.put(physicalProperties, 
costAndGroupExpr);
-            } else {
-                if (costAndGroupExpr.first < 
target.lowestCostPlans.get(physicalProperties).first) {
-                    target.lowestCostPlans.put(physicalProperties, 
costAndGroupExpr);
-                }
-            }
-        });
-        lowestCostPlans.clear();
-    }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/RequestPropertyDeriver.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/RequestPropertyDeriver.java
index 15468686e1..96379b6339 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/RequestPropertyDeriver.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/properties/RequestPropertyDeriver.java
@@ -85,17 +85,17 @@ public class RequestPropertyDeriver extends 
PlanVisitor<Void, PlanContext> {
     public Void visitPhysicalAggregate(PhysicalAggregate<? extends Plan> agg, 
PlanContext context) {
         // 1. first phase agg just return any
         if (agg.getAggPhase().isLocal() && !agg.isFinalPhase()) {
-            addToRequestPropertyToChildren(PhysicalProperties.ANY);
+            addRequestPropertyToChildren(PhysicalProperties.ANY);
             return null;
         }
         if (agg.getAggPhase() == AggPhase.GLOBAL && !agg.isFinalPhase()) {
-            addToRequestPropertyToChildren(requestPropertyFromParent);
+            addRequestPropertyToChildren(requestPropertyFromParent);
             return null;
         }
         // 2. second phase agg, need to return shuffle with partition key
         List<Expression> partitionExpressions = agg.getPartitionExpressions();
         if (partitionExpressions.isEmpty()) {
-            addToRequestPropertyToChildren(PhysicalProperties.GATHER);
+            addRequestPropertyToChildren(PhysicalProperties.GATHER);
             return null;
         }
         // TODO: when parent is a join node,
@@ -105,7 +105,7 @@ public class RequestPropertyDeriver extends 
PlanVisitor<Void, PlanContext> {
                     .map(SlotReference.class::cast)
                     .map(SlotReference::getExprId)
                     .collect(Collectors.toList());
-            addToRequestPropertyToChildren(
+            addRequestPropertyToChildren(
                     PhysicalProperties.createHash(new 
DistributionSpecHash(partitionedSlots, ShuffleType.AGGREGATE)));
             return null;
         }
@@ -118,34 +118,33 @@ public class RequestPropertyDeriver extends 
PlanVisitor<Void, PlanContext> {
 
     @Override
     public Void visitPhysicalQuickSort(PhysicalQuickSort<? extends Plan> sort, 
PlanContext context) {
-        addToRequestPropertyToChildren(PhysicalProperties.ANY);
+        addRequestPropertyToChildren(PhysicalProperties.ANY);
         return null;
     }
 
     @Override
     public Void visitPhysicalLocalQuickSort(PhysicalLocalQuickSort<? extends 
Plan> sort, PlanContext context) {
         // TODO: rethink here, should we throw exception directly?
-        addToRequestPropertyToChildren(PhysicalProperties.ANY);
+        addRequestPropertyToChildren(PhysicalProperties.ANY);
         return null;
     }
 
     @Override
     public Void visitPhysicalHashJoin(PhysicalHashJoin<? extends Plan, ? 
extends Plan> hashJoin, PlanContext context) {
-        // for broadcast join
-        if (JoinUtils.couldBroadcast(hashJoin)) {
-            addToRequestPropertyToChildren(PhysicalProperties.ANY, 
PhysicalProperties.REPLICATED);
-        }
-
         // for shuffle join
         if (JoinUtils.couldShuffle(hashJoin)) {
             Pair<List<ExprId>, List<ExprId>> onClauseUsedSlots = 
JoinUtils.getOnClauseUsedSlots(hashJoin);
             // shuffle join
-            addToRequestPropertyToChildren(
+            addRequestPropertyToChildren(
                     PhysicalProperties.createHash(
                             new DistributionSpecHash(onClauseUsedSlots.first, 
ShuffleType.JOIN)),
                     PhysicalProperties.createHash(
                             new DistributionSpecHash(onClauseUsedSlots.second, 
ShuffleType.JOIN)));
         }
+        // for broadcast join
+        if (JoinUtils.couldBroadcast(hashJoin)) {
+            addRequestPropertyToChildren(PhysicalProperties.ANY, 
PhysicalProperties.REPLICATED);
+        }
 
         return null;
     }
@@ -154,13 +153,13 @@ public class RequestPropertyDeriver extends 
PlanVisitor<Void, PlanContext> {
     public Void visitPhysicalNestedLoopJoin(
             PhysicalNestedLoopJoin<? extends Plan, ? extends Plan> 
nestedLoopJoin, PlanContext context) {
         // TODO: currently doris only use NLJ to do cross join, update this if 
we use NLJ to do other joins.
-        addToRequestPropertyToChildren(PhysicalProperties.ANY, 
PhysicalProperties.REPLICATED);
+        addRequestPropertyToChildren(PhysicalProperties.ANY, 
PhysicalProperties.REPLICATED);
         return null;
     }
 
     @Override
     public Void visitPhysicalAssertNumRows(PhysicalAssertNumRows<? extends 
Plan> assertNumRows, PlanContext context) {
-        addToRequestPropertyToChildren(PhysicalProperties.GATHER);
+        addRequestPropertyToChildren(PhysicalProperties.GATHER);
         return null;
     }
 
@@ -168,7 +167,7 @@ public class RequestPropertyDeriver extends 
PlanVisitor<Void, PlanContext> {
      * helper function to assemble request children physical properties
      * @param physicalProperties one set request properties for children
      */
-    private void addToRequestPropertyToChildren(PhysicalProperties... 
physicalProperties) {
+    private void addRequestPropertyToChildren(PhysicalProperties... 
physicalProperties) {
         requestPropertyToChildren.add(Lists.newArrayList(physicalProperties));
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/statistics/StatsDeriveResult.java 
b/fe/fe-core/src/main/java/org/apache/doris/statistics/StatsDeriveResult.java
index 74f5bac4f4..3cd7026f60 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/statistics/StatsDeriveResult.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/statistics/StatsDeriveResult.java
@@ -31,6 +31,7 @@ import java.util.Set;
  */
 public class StatsDeriveResult {
     private final double rowCount;
+    private double computeSize = -1D;
 
     private int width = 1;
     private double penalty = 0.0;
@@ -79,8 +80,12 @@ public class StatsDeriveResult {
     }
 
     public double computeSize() {
-        return Math.max(1, slotIdToColumnStats.values().stream().map(s -> 
s.dataSize).reduce(0D, Double::sum))
-                * rowCount;
+        if (computeSize < 0) {
+            computeSize = Math.max(1, slotIdToColumnStats.values().stream()
+                    .map(s -> s.dataSize).reduce(0D, Double::sum)
+            ) * rowCount;
+        }
+        return computeSize;
     }
 
     /**
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/properties/RequestPropertyDeriverTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/properties/RequestPropertyDeriverTest.java
index 90d3010446..b6330c2948 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/properties/RequestPropertyDeriverTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/properties/RequestPropertyDeriverTest.java
@@ -132,11 +132,11 @@ public class RequestPropertyDeriverTest {
                 = 
requestPropertyDeriver.getRequestChildrenPropertyList(groupExpression);
 
         List<List<PhysicalProperties>> expected = Lists.newArrayList();
-        expected.add(Lists.newArrayList(PhysicalProperties.ANY, 
PhysicalProperties.REPLICATED));
         expected.add(Lists.newArrayList(
                 new PhysicalProperties(new 
DistributionSpecHash(Lists.newArrayList(new ExprId(0)), ShuffleType.JOIN)),
                 new PhysicalProperties(new 
DistributionSpecHash(Lists.newArrayList(new ExprId(1)), ShuffleType.JOIN))
         ));
+        expected.add(Lists.newArrayList(PhysicalProperties.ANY, 
PhysicalProperties.REPLICATED));
         Assertions.assertEquals(expected, actual);
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to