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

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


The following commit(s) were added to refs/heads/branch-2.1 by this push:
     new 3f6c71e47b0 [enhancement](Nereids) fast compute hash code of deep 
expression tree to reduce conflict (#38981) (#39133)
3f6c71e47b0 is described below

commit 3f6c71e47b0507c8e9a40f5ed0a75d353f760c06
Author: 924060929 <924060...@qq.com>
AuthorDate: Fri Aug 9 16:28:24 2024 +0800

    [enhancement](Nereids) fast compute hash code of deep expression tree to 
reduce conflict (#38981) (#39133)
    
    The Expression.hashCode default is getClass().hashCode(), just contains one 
level information, so the lots of expressions which is same type will return 
the same hash code and conflict, then compare deeply in the HashMap cause 
inefficient and hold table lock for long time.
    
    This pr support fast compute hash code by the bottom literal and slot, 
reduce the compare expression time because of the conflict of hash code
    
    In my test case, the sql planner time can reduce from 20 minutes(not 
finished) to 35 seconds
---
 .../post/CommonSubExpressionCollector.java         | 14 +++++++++----
 .../rules/exploration/mv/PredicatesSplitter.java   |  8 ++++----
 .../nereids/rules/rewrite/EliminateNotNull.java    |  2 +-
 .../nereids/trees/expressions/Expression.java      | 23 ++++++++++++++++++++--
 .../nereids/trees/expressions/Placeholder.java     | 10 ++++++++++
 .../nereids/trees/expressions/SlotReference.java   |  5 +++++
 .../nereids/trees/expressions/literal/Literal.java |  5 +++++
 .../org/apache/doris/qe/PointQueryExecutor.java    |  2 +-
 .../rules/expression/PredicatesSplitterTest.java   |  2 +-
 9 files changed, 58 insertions(+), 13 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/CommonSubExpressionCollector.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/CommonSubExpressionCollector.java
index 5abc5f6f60f..877e411a539 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/CommonSubExpressionCollector.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/CommonSubExpressionCollector.java
@@ -37,8 +37,15 @@ public class CommonSubExpressionCollector extends 
ExpressionVisitor<Integer, Voi
         if (expr.children().isEmpty()) {
             return 0;
         }
-        return 
collectCommonExpressionByDepth(expr.children().stream().map(child ->
-                child.accept(this, context)).reduce(Math::max).map(m -> m + 
1).orElse(1), expr);
+        return collectCommonExpressionByDepth(
+                expr.children()
+                        .stream()
+                        .map(child -> child.accept(this, context))
+                        .reduce(Math::max)
+                        .map(m -> m + 1)
+                        .orElse(1),
+                expr
+        );
     }
 
     private int collectCommonExpressionByDepth(int depth, Expression expr) {
@@ -53,7 +60,6 @@ public class CommonSubExpressionCollector extends 
ExpressionVisitor<Integer, Voi
 
     public static Set<Expression> getExpressionsFromDepthMap(
             int depth, Map<Integer, Set<Expression>> depthMap) {
-        depthMap.putIfAbsent(depth, new LinkedHashSet<>());
-        return depthMap.get(depth);
+        return depthMap.computeIfAbsent(depth, d -> new LinkedHashSet<>());
     }
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/PredicatesSplitter.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/PredicatesSplitter.java
index f1c0ae8f96a..f7182eeab73 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/PredicatesSplitter.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/mv/PredicatesSplitter.java
@@ -28,7 +28,7 @@ import 
org.apache.doris.nereids.trees.expressions.literal.Literal;
 import 
org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionVisitor;
 import org.apache.doris.nereids.util.ExpressionUtils;
 
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -39,9 +39,9 @@ import java.util.Set;
  */
 public class PredicatesSplitter {
 
-    private final Set<Expression> equalPredicates = new HashSet<>();
-    private final Set<Expression> rangePredicates = new HashSet<>();
-    private final Set<Expression> residualPredicates = new HashSet<>();
+    private final Set<Expression> equalPredicates = new LinkedHashSet<>();
+    private final Set<Expression> rangePredicates = new LinkedHashSet<>();
+    private final Set<Expression> residualPredicates = new LinkedHashSet<>();
     private final List<Expression> conjunctExpressions;
 
     public PredicatesSplitter(Expression target) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateNotNull.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateNotNull.java
index 22393cb55f8..b3fe2e1aa91 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateNotNull.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/EliminateNotNull.java
@@ -81,7 +81,7 @@ public class EliminateNotNull implements RewriteRuleFactory {
         // predicatesNotContainIsNotNull infer nonNullable slots: `id`
         // slotsFromIsNotNull: `id`, `name`
         // remove `name` (it's generated), remove `id` (because `id > 0` 
already contains it)
-        Set<Expression> predicatesNotContainIsNotNull = Sets.newHashSet();
+        Set<Expression> predicatesNotContainIsNotNull = 
Sets.newLinkedHashSet();
         List<Slot> slotsFromIsNotNull = Lists.newArrayList();
 
         for (Expression expr : exprs) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java
index d7f400955c0..e355cd204cd 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Expression.java
@@ -70,6 +70,7 @@ public abstract class Expression extends 
AbstractTreeNode<Expression> implements
     private final boolean compareWidthAndDepth;
     private final Supplier<Set<Slot>> inputSlots = Suppliers.memoize(
             () -> collect(e -> e instanceof Slot && !(e instanceof 
ArrayItemSlot)));
+    private final int fastChildrenHashCode;
 
     protected Expression(Expression... children) {
         super(children);
@@ -80,12 +81,14 @@ public abstract class Expression extends 
AbstractTreeNode<Expression> implements
                 this.depth = 1;
                 this.width = 1;
                 this.compareWidthAndDepth = supportCompareWidthAndDepth();
+                this.fastChildrenHashCode = 0;
                 break;
             case 1:
                 Expression child = children[0];
                 this.depth = child.depth + 1;
                 this.width = child.width;
                 this.compareWidthAndDepth = child.compareWidthAndDepth && 
supportCompareWidthAndDepth();
+                this.fastChildrenHashCode = child.fastChildrenHashCode() + 1;
                 break;
             case 2:
                 Expression left = children[0];
@@ -94,21 +97,25 @@ public abstract class Expression extends 
AbstractTreeNode<Expression> implements
                 this.width = left.width + right.width;
                 this.compareWidthAndDepth =
                         left.compareWidthAndDepth && 
right.compareWidthAndDepth && supportCompareWidthAndDepth();
+                this.fastChildrenHashCode = left.fastChildrenHashCode() + 
right.fastChildrenHashCode() + 2;
                 break;
             default:
                 int maxChildDepth = 0;
                 int sumChildWidth = 0;
                 boolean compareWidthAndDepth = true;
+                int fastChildrenHashCode = 0;
                 for (Expression expression : children) {
                     child = expression;
                     maxChildDepth = Math.max(child.depth, maxChildDepth);
                     sumChildWidth += child.width;
                     hasUnbound |= child.hasUnbound;
                     compareWidthAndDepth &= child.compareWidthAndDepth;
+                    fastChildrenHashCode = fastChildrenHashCode + 
expression.fastChildrenHashCode() + 1;
                 }
                 this.depth = maxChildDepth + 1;
                 this.width = sumChildWidth;
                 this.compareWidthAndDepth = compareWidthAndDepth;
+                this.fastChildrenHashCode = fastChildrenHashCode;
         }
 
         checkLimit();
@@ -129,12 +136,14 @@ public abstract class Expression extends 
AbstractTreeNode<Expression> implements
                 this.depth = 1;
                 this.width = 1;
                 this.compareWidthAndDepth = supportCompareWidthAndDepth();
+                this.fastChildrenHashCode = 0;
                 break;
             case 1:
                 Expression child = children.get(0);
                 this.depth = child.depth + 1;
                 this.width = child.width;
                 this.compareWidthAndDepth = child.compareWidthAndDepth && 
supportCompareWidthAndDepth();
+                this.fastChildrenHashCode = child.fastChildrenHashCode() + 1;
                 break;
             case 2:
                 Expression left = children.get(0);
@@ -143,21 +152,25 @@ public abstract class Expression extends 
AbstractTreeNode<Expression> implements
                 this.width = left.width + right.width;
                 this.compareWidthAndDepth =
                         left.compareWidthAndDepth && 
right.compareWidthAndDepth && supportCompareWidthAndDepth();
+                this.fastChildrenHashCode = left.fastChildrenHashCode() + 
right.fastChildrenHashCode() + 2;
                 break;
             default:
                 int maxChildDepth = 0;
                 int sumChildWidth = 0;
                 boolean compareWidthAndDepth = true;
+                int fastChildrenhashCode = 0;
                 for (Expression expression : children) {
                     child = expression;
                     maxChildDepth = Math.max(child.depth, maxChildDepth);
                     sumChildWidth += child.width;
                     hasUnbound |= child.hasUnbound;
                     compareWidthAndDepth &= child.compareWidthAndDepth;
+                    fastChildrenhashCode = fastChildrenhashCode + 
expression.fastChildrenHashCode() + 1;
                 }
                 this.depth = maxChildDepth + 1;
                 this.width = sumChildWidth;
                 this.compareWidthAndDepth = compareWidthAndDepth && 
supportCompareWidthAndDepth();
+                this.fastChildrenHashCode = fastChildrenhashCode;
         }
 
         checkLimit();
@@ -211,6 +224,10 @@ public abstract class Expression extends 
AbstractTreeNode<Expression> implements
         return checkInputDataTypesInternal();
     }
 
+    public int fastChildrenHashCode() {
+        return fastChildrenHashCode;
+    }
+
     protected TypeCheckResult checkInputDataTypesInternal() {
         return TypeCheckResult.SUCCESS;
     }
@@ -406,7 +423,9 @@ public abstract class Expression extends 
AbstractTreeNode<Expression> implements
             return false;
         }
         Expression that = (Expression) o;
-        if ((compareWidthAndDepth && (this.width != that.width || this.depth 
!= that.depth))
+        if ((compareWidthAndDepth
+                && (this.width != that.width || this.depth != that.depth
+                    || this.fastChildrenHashCode != that.fastChildrenHashCode))
                 || arity() != that.arity() || !extraEquals(that)) {
             return false;
         }
@@ -430,7 +449,7 @@ public abstract class Expression extends 
AbstractTreeNode<Expression> implements
 
     @Override
     public int hashCode() {
-        return getClass().hashCode();
+        return getClass().hashCode() + fastChildrenHashCode();
     }
 
     /**
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Placeholder.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Placeholder.java
index 0432beadd2c..c79c2d9db6d 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Placeholder.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Placeholder.java
@@ -60,11 +60,21 @@ public class Placeholder extends Expression implements 
LeafExpression {
         return true;
     }
 
+    @Override
+    public String toString() {
+        return "$" + placeholderId.asInt();
+    }
+
     @Override
     public String toSql() {
         return "?";
     }
 
+    @Override
+    public int fastChildrenHashCode() {
+        return placeholderId.asInt();
+    }
+
     @Override
     public DataType getDataType() throws UnboundException {
         return NullType.INSTANCE;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java
index 145d8dd29f7..679c8ab73bd 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/SlotReference.java
@@ -237,6 +237,11 @@ public class SlotReference extends Slot {
         return exprId.asInt();
     }
 
+    @Override
+    public int fastChildrenHashCode() {
+        return exprId.asInt();
+    }
+
     @Override
     public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
         return visitor.visitSlotReference(this, context);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
index fe53cbf0e2a..e8e37aaf697 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Literal.java
@@ -365,6 +365,11 @@ public abstract class Literal extends Expression 
implements LeafExpression, Comp
         return Objects.hashCode(getValue());
     }
 
+    @Override
+    public int fastChildrenHashCode() {
+        return Objects.hashCode(getValue());
+    }
+
     @Override
     public String toString() {
         return String.valueOf(getValue());
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java
index b0af8431471..68b1eb6ab93 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java
@@ -136,7 +136,7 @@ public class PointQueryExecutor implements CoordInterface {
             } else if (binaryPredicate.getChild(1) instanceof LiteralExpr) {
                 binaryPredicate.setChild(1, conjunctVals.get(i));
             } else {
-                Preconditions.checkState(false, "Should conatains literal in " 
+ binaryPredicate.toSqlImpl());
+                Preconditions.checkState(false, "Should contains literal in " 
+ binaryPredicate.toSqlImpl());
             }
         }
     }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/PredicatesSplitterTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/PredicatesSplitterTest.java
index 56c0a6b8341..0374244ce56 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/PredicatesSplitterTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/PredicatesSplitterTest.java
@@ -61,7 +61,7 @@ public class PredicatesSplitterTest extends 
ExpressionRewriteTestHelper {
             String expectedRangeExpr,
             String expectedResidualExpr) {
 
-        Map<String, Slot> mem = Maps.newHashMap();
+        Map<String, Slot> mem = Maps.newLinkedHashMap();
         Expression targetExpr = 
replaceUnboundSlot(PARSER.parseExpression(expression), mem);
         SplitPredicate splitPredicate = Predicates.splitPredicates(targetExpr);
 


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

Reply via email to