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

morrysnow pushed a commit to branch vector-index-dev
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/vector-index-dev by this push:
     new 9421e5afdce [opt](vector) only extract l2_distance from filter
9421e5afdce is described below

commit 9421e5afdce9314a42357584f322c33cacaf1b4d
Author: morrySnow <zhangwen...@selectdb.com>
AuthorDate: Tue May 20 19:46:09 2025 +0800

    [opt](vector) only extract l2_distance from filter
---
 .../org/apache/doris/analysis/SlotDescriptor.java  |   2 +-
 .../post/CommonSubExpressionCollector.java         |   3 +-
 .../nereids/processor/post/PlanPostProcessors.java |   8 +-
 .../PushDownVirtualColumnsIntoOlapScan.java        | 118 +++++++++++----------
 4 files changed, 67 insertions(+), 64 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java
index 5af4b378274..5d0ec929ad6 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java
@@ -345,7 +345,7 @@ public class SlotDescriptor {
                 .add("type", typeStr).add("materialized", 
isMaterialized).add("byteSize", byteSize)
                 .add("byteOffset", byteOffset).add("slotIdx", 
slotIdx).add("nullable", getIsNullable())
                 .add("isAutoIncrement", isAutoInc).add("subColPath", 
subColPath)
-                .add("virtualColumn", virtualColumn.toSql()).toString();
+                .add("virtualColumn", virtualColumn == null ? null : 
virtualColumn.toSql()).toString();
     }
 
     @Override
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 29c70b7ed3f..520902c0439 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
@@ -61,7 +61,8 @@ public class CommonSubExpressionCollector extends 
ExpressionVisitor<Integer, Boo
         // ArrayItemSlot and ArrayItemReference could not be common expressions
         // TODO: could not extract common expression when expression contains 
same lambda expression
         //   because ArrayItemSlot in Lambda are not same.
-        if (!(inLambda && expr.containsType(ArrayItemSlot.class, 
ArrayItemReference.class))) {
+        if (expressions.contains(expr)
+                && !(inLambda && expr.containsType(ArrayItemSlot.class, 
ArrayItemReference.class))) {
             Set<Expression> commonExpression = 
getExpressionsFromDepthMap(depth, commonExprByDepth);
             commonExpression.add(expr);
         }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/PlanPostProcessors.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/PlanPostProcessors.java
index 86801dc1b26..a8654e27291 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/PlanPostProcessors.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/PlanPostProcessors.java
@@ -62,10 +62,10 @@ public class PlanPostProcessors {
         builder.add(new RemoveUselessProjectPostProcessor());
         builder.add(new MergeProjectPostProcessor());
         builder.add(new RecomputeLogicalPropertiesProcessor());
-        // if 
(cascadesContext.getConnectContext().getSessionVariable().enableAggregateCse) {
-        //     builder.add(new ProjectAggregateExpressionsForCse());
-        // }
-        // builder.add(new CommonSubExpressionOpt());
+        if 
(cascadesContext.getConnectContext().getSessionVariable().enableAggregateCse) {
+            builder.add(new ProjectAggregateExpressionsForCse());
+        }
+        builder.add(new CommonSubExpressionOpt());
         // DO NOT replace PLAN NODE from here
         if 
(cascadesContext.getConnectContext().getSessionVariable().pushTopnToAgg) {
             builder.add(new PushTopnToAgg());
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScan.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScan.java
index 56ee140169c..536f3e79f35 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScan.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/PushDownVirtualColumnsIntoOlapScan.java
@@ -17,84 +17,86 @@
 
 package org.apache.doris.nereids.rules.rewrite;
 
-import org.apache.doris.nereids.processor.post.CommonSubExpressionCollector;
-import 
org.apache.doris.nereids.processor.post.CommonSubExpressionOpt.ExpressionReplacer;
 import org.apache.doris.nereids.rules.Rule;
 import org.apache.doris.nereids.rules.RuleType;
 import org.apache.doris.nereids.trees.expressions.Alias;
 import org.apache.doris.nereids.trees.expressions.Expression;
 import org.apache.doris.nereids.trees.expressions.NamedExpression;
-import org.apache.doris.nereids.trees.expressions.Slot;
-import org.apache.doris.nereids.trees.expressions.WhenClause;
+import org.apache.doris.nereids.trees.expressions.functions.scalar.L2Distance;
+import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
 import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
 import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
 import org.apache.doris.nereids.util.ExpressionUtils;
 
-import com.google.common.collect.Lists;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Maps;
 
-import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 
 /**
  * extract virtual column from filter and push down them into olap scan.
  */
-public class PushDownVirtualColumnsIntoOlapScan extends OneRewriteRuleFactory {
+public class PushDownVirtualColumnsIntoOlapScan implements RewriteRuleFactory {
 
     @Override
-    public Rule build() {
-        return logicalProject(logicalFilter(logicalOlapScan()
-                .when(s -> s.getVirtualColumns().isEmpty())))
-                .then(project -> {
-                    // 1. extract filter common expr
-                    // 2. generate virtual column from common expr and add 
them to scan
-                    // 3. replace filter
-                    // 4. replace project
-                    LogicalFilter<LogicalOlapScan> filter = project.child();
-                    LogicalOlapScan logicalOlapScan = filter.child();
-                    CommonSubExpressionCollector collector = new 
CommonSubExpressionCollector();
-                    for (Expression expr : filter.getConjuncts()) {
-                        collector.collect(expr);
-                    }
-                    Map<Expression, Alias> aliasMap = new LinkedHashMap<>();
-                    if (!collector.commonExprByDepth.isEmpty()) {
-                        for (int i = 1; i <= 
collector.commonExprByDepth.size(); i++) {
-                            Set<Expression> exprsInDepth = 
CommonSubExpressionCollector
-                                    .getExpressionsFromDepthMap(i, 
collector.commonExprByDepth);
-                            exprsInDepth.forEach(expr -> {
-                                if (!(expr instanceof WhenClause)) {
-                                    // case whenClause1 whenClause2 END
-                                    // whenClause should not be regarded as 
common-sub-expression, because
-                                    // cse will be replaced by a slot, after 
rewrite the case clause becomes:
-                                    // 'case slot whenClause2 END'
-                                    // This is illegal.
-                                    Expression rewritten = 
expr.accept(ExpressionReplacer.INSTANCE, aliasMap);
-                                    // if rewritten is already alias, use it 
directly,
-                                    // because in materialized view rewriting
-                                    // Should keep out slot immutably after 
rewritten successfully
-                                    aliasMap.put(expr, rewritten instanceof 
Alias
-                                            ? (Alias) rewritten : new 
Alias(rewritten));
-                                }
-                            });
-                        }
-                    }
-                    List<NamedExpression> virtualColumns = 
Lists.newArrayList();
-                    Map<Expression, Slot> replaceMap = Maps.newHashMap();
-                    for (Map.Entry<Expression, Alias> entry : 
aliasMap.entrySet()) {
-                        Alias alias = entry.getValue();
-                        replaceMap.put(entry.getKey(), alias.toSlot());
-                        virtualColumns.add(alias);
-                    }
-                    logicalOlapScan = 
logicalOlapScan.withVirtualColumns(virtualColumns);
-                    Set<Expression> conjuncts = 
ExpressionUtils.replace(filter.getConjuncts(), replaceMap);
-                    List<NamedExpression> projections = 
ExpressionUtils.replace(
-                            (List) project.getProjects(), replaceMap);
-                    LogicalFilter<?> newFilter = 
filter.withConjunctsAndChild(conjuncts, logicalOlapScan);
-                    LogicalProject<?> newProject = 
project.withProjectsAndChild(projections, newFilter);
-                    return newProject;
-                }).toRule(RuleType.PUSH_DOWN_VIRTUAL_COLUMNS_INTO_OLAP_SCAN);
+    public List<Rule> buildRules() {
+        return ImmutableList.of(
+                logicalProject(logicalFilter(logicalOlapScan()
+                        .when(s -> s.getVirtualColumns().isEmpty())))
+                        .then(project -> {
+                            LogicalFilter<LogicalOlapScan> filter = 
project.child();
+                            LogicalOlapScan scan = filter.child();
+                            return pushDown(filter, scan, 
Optional.of(project));
+                        
}).toRule(RuleType.PUSH_DOWN_VIRTUAL_COLUMNS_INTO_OLAP_SCAN),
+                logicalFilter(logicalOlapScan()
+                        .when(s -> s.getVirtualColumns().isEmpty()))
+                        .then(filter -> {
+                            LogicalOlapScan scan = filter.child();
+                            return pushDown(filter, scan, Optional.empty());
+                        
}).toRule(RuleType.PUSH_DOWN_VIRTUAL_COLUMNS_INTO_OLAP_SCAN)
+
+        );
+    }
+
+    private Plan pushDown(LogicalFilter<LogicalOlapScan> filter, 
LogicalOlapScan logicalOlapScan,
+            Optional<LogicalProject<?>> optionalProject) {
+        // 1. extract filter l2_distance
+        // 2. generate virtual column from l2_distance and add them to scan
+        // 3. replace filter
+        // 4. replace project
+        Map<Expression, Expression> replaceMap = Maps.newHashMap();
+        for (Expression conjunct : filter.getConjuncts()) {
+            Set<Expression> l2Distances = 
conjunct.collect(L2Distance.class::isInstance);
+            for (Expression l2Distance : l2Distances) {
+                if (replaceMap.containsKey(l2Distance)) {
+                    continue;
+                }
+                Alias alias = new Alias(l2Distance);
+                replaceMap.put(l2Distance, alias.toSlot());
+            }
+        }
+        if (replaceMap.isEmpty()) {
+            return null;
+        }
+        ImmutableList.Builder<NamedExpression> virtualColumnsBuilder = 
ImmutableList.builder();
+        for (Expression expression : replaceMap.values()) {
+            virtualColumnsBuilder.add((NamedExpression) expression);
+        }
+        logicalOlapScan = 
logicalOlapScan.withVirtualColumns(virtualColumnsBuilder.build());
+        Set<Expression> conjuncts = 
ExpressionUtils.replace(filter.getConjuncts(), replaceMap);
+        Plan plan = filter.withConjunctsAndChild(conjuncts, logicalOlapScan);
+        if (optionalProject.isPresent()) {
+            LogicalProject<?> project = optionalProject.get();
+            List<NamedExpression> projections = ExpressionUtils.replace(
+                    (List) project.getProjects(), replaceMap);
+            plan = project.withProjectsAndChild(projections, plan);
+        } else {
+            plan = new LogicalProject<>((List) filter.getOutput(), plan);
+        }
+        return plan;
     }
 }


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

Reply via email to