You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by en...@apache.org on 2024/01/24 10:02:33 UTC

(doris) branch tpcds updated: set flag to indicate if bloom filter size is calculated by NDV (#30322)

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

englefly pushed a commit to branch tpcds
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/tpcds by this push:
     new 530faf47da3 set flag to indicate if bloom filter size is calculated by NDV (#30322)
530faf47da3 is described below

commit 530faf47da3825a6643e0942d436003efddb91a6
Author: minghong <en...@gmail.com>
AuthorDate: Wed Jan 24 18:02:22 2024 +0800

    set flag to indicate if bloom filter size is calculated by NDV (#30322)
---
 .../glue/translator/RuntimeFilterTranslator.java   | 26 +++++++-------
 .../processor/post/RuntimeFilterContext.java       |  2 +-
 .../processor/post/RuntimeFilterGenerator.java     | 14 +++++---
 .../trees/plans/physical/AbstractPhysicalPlan.java |  9 ++---
 .../trees/plans/physical/PhysicalProject.java      | 11 +++++-
 .../trees/plans/physical/RuntimeFilter.java        | 41 ++++++++++++----------
 .../apache/doris/nereids/util/ExpressionUtils.java | 20 +++++++++++
 .../org/apache/doris/planner/RuntimeFilter.java    | 12 +++++++
 .../nereids/postprocess/RuntimeFilterTest.java     |  4 +--
 gensrc/thrift/PlanNodes.thrift                     |  5 +++
 10 files changed, 98 insertions(+), 46 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/RuntimeFilterTranslator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/RuntimeFilterTranslator.java
index 30a69ff97de..a2fbc28ecd8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/RuntimeFilterTranslator.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/glue/translator/RuntimeFilterTranslator.java
@@ -115,30 +115,27 @@ public class RuntimeFilterTranslator {
         List<Map<TupleId, List<SlotId>>> targetTupleIdMapList = new ArrayList<>();
         List<ScanNode> scanNodeList = new ArrayList<>();
         boolean hasInvalidTarget = false;
-        for (int i = 0; i < filter.getTargetExprs().size(); i++) {
-            Slot curTargetExpr = filter.getTargetExprs().get(i);
+        for (int i = 0; i < filter.getTargetExpressions().size(); i++) {
+            Slot curTargetSlot = filter.getTargetSlots().get(i);
             Expression curTargetExpression = filter.getTargetExpressions().get(i);
-            Expr target = context.getExprIdToOlapScanNodeSlotRef().get(curTargetExpr.getExprId());
+            Expr target = context.getExprIdToOlapScanNodeSlotRef().get(curTargetSlot.getExprId());
             if (target == null) {
                 context.setTargetNullCount();
                 hasInvalidTarget = true;
                 break;
             }
-            ScanNode scanNode = context.getScanNodeOfLegacyRuntimeFilterTarget().get(curTargetExpr);
+            ScanNode scanNode = context.getScanNodeOfLegacyRuntimeFilterTarget().get(curTargetSlot);
             Expr targetExpr;
-            if (filter.getType() == TRuntimeFilterType.BITMAP) {
-                if (curTargetExpression.equals(curTargetExpr)) {
-                    targetExpr = target;
-                } else {
-                    RuntimeFilterExpressionTranslator translator = new RuntimeFilterExpressionTranslator(
-                            context.getExprIdToOlapScanNodeSlotRef());
-                    targetExpr = curTargetExpression.accept(translator, ctx);
-                }
-            } else {
+            if (curTargetSlot.equals(curTargetExpression)) {
                 targetExpr = target;
+            } else {
+                RuntimeFilterExpressionTranslator translator = new RuntimeFilterExpressionTranslator(
+                        context.getExprIdToOlapScanNodeSlotRef());
+                targetExpr = curTargetExpression.accept(translator, ctx);
             }
+
             // adjust data type
-            if (!src.getType().equals(target.getType()) && filter.getType() != TRuntimeFilterType.BITMAP) {
+            if (!src.getType().equals(targetExpr.getType()) && filter.getType() != TRuntimeFilterType.BITMAP) {
                 targetExpr = new CastExpr(src.getType(), targetExpr);
             }
             SlotRef targetSlot = target.getSrcSlotRef();
@@ -168,6 +165,7 @@ public class RuntimeFilterTranslator {
                         scanNode, targetExpr, true, isLocalTarget));
             }
             origFilter.setBitmapFilterNotIn(filter.isBitmapFilterNotIn());
+            origFilter.setBloomFilterSizeCalculatedByNdv(filter.isBloomFilterSizeCalculatedByNdv());
             org.apache.doris.planner.RuntimeFilter finalizedFilter = finalize(origFilter);
             scanNodeList.stream().filter(e -> e.getStatisticalType() == StatisticalType.CTE_SCAN_NODE)
                                  .forEach(f -> {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/RuntimeFilterContext.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/RuntimeFilterContext.java
index 5e412f61ca3..2e8055ca783 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/RuntimeFilterContext.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/RuntimeFilterContext.java
@@ -206,7 +206,7 @@ public class RuntimeFilterContext {
     }
 
     public void setTargetExprIdToFilter(ExprId id, RuntimeFilter filter) {
-        Preconditions.checkArgument(filter.getTargetExprs().stream().anyMatch(expr -> expr.getExprId() == id));
+        Preconditions.checkArgument(filter.getTargetSlots().stream().anyMatch(expr -> expr.getExprId() == id));
         this.targetExprIdToFilter.computeIfAbsent(id, k -> Lists.newArrayList()).add(filter);
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/RuntimeFilterGenerator.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/RuntimeFilterGenerator.java
index 8a75ad36c5a..2a5d37e090d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/RuntimeFilterGenerator.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/processor/post/RuntimeFilterGenerator.java
@@ -186,7 +186,8 @@ public class RuntimeFilterGenerator extends PlanPostProcessor {
                 PhysicalRelation scan = ctx.getAliasTransferPair(targetSlot).first;
                 RuntimeFilter filter = new RuntimeFilter(generator.getNextId(),
                         bitmapContains.child(0), ImmutableList.of(scanSlot),
-                        ImmutableList.of(bitmapContains.child(1)), type, i, join, isNot, -1L, scan);
+                        ImmutableList.of(bitmapContains.child(1)), type, i, join, isNot, -1L,
+                        false, scan);
                 scan.addAppliedRuntimeFilter(filter);
                 ctx.addJoinToTargetMap(join, scanSlot.getExprId());
                 ctx.setTargetExprIdToFilter(scanSlot.getExprId(), filter);
@@ -265,7 +266,7 @@ public class RuntimeFilterGenerator extends PlanPostProcessor {
                 long buildSideNdv = getBuildSideNdv(join, compare);
                 RuntimeFilter filter = new RuntimeFilter(generator.getNextId(),
                         compare.child(1), ImmutableList.of(olapScanSlot), ImmutableList.of(olapScanSlot),
-                        TRuntimeFilterType.MIN_MAX, exprOrder, join, true, buildSideNdv,
+                        TRuntimeFilterType.MIN_MAX, exprOrder, join, true, buildSideNdv, false,
                         getMinMaxType(compare), scan);
                 scan.addAppliedRuntimeFilter(filter);
                 ctx.addJoinToTargetMap(join, olapScanSlot.getExprId());
@@ -315,7 +316,7 @@ public class RuntimeFilterGenerator extends PlanPostProcessor {
             if (expression.children().isEmpty()) {
                 continue;
             }
-            Expression expr = ExpressionUtils.getExpressionCoveredByCast(expression.child(0));
+            Expression expr = ExpressionUtils.getSingleNumericSlotOrExpressionCoveredByCast(expression.child(0));
             if (expr instanceof NamedExpression
                     && ctx.aliasTransferMapContains((NamedExpression) expr)) {
                 if (expression instanceof Alias) {
@@ -357,7 +358,7 @@ public class RuntimeFilterGenerator extends PlanPostProcessor {
     }
 
     public static Slot checkTargetChild(Expression leftChild) {
-        Expression expression = ExpressionUtils.getExpressionCoveredByCast(leftChild);
+        Expression expression = ExpressionUtils.getSingleNumericSlotOrExpressionCoveredByCast(leftChild);
         return expression instanceof Slot ? ((Slot) expression) : null;
     }
 
@@ -611,6 +612,7 @@ public class RuntimeFilterGenerator extends PlanPostProcessor {
                         (SlotReference) targetExpr, ctx);
                 if (!pushDownBasicTableInfos.isEmpty()) {
                     List<Slot> targetList = new ArrayList<>();
+                    List<Expression> targetExpressions = new ArrayList<>();
                     List<PhysicalRelation> targetNodes = new ArrayList<>();
                     for (Map.Entry<Slot, PhysicalRelation> entry : pushDownBasicTableInfos.entrySet()) {
                         Slot targetSlot = entry.getKey();
@@ -619,6 +621,7 @@ public class RuntimeFilterGenerator extends PlanPostProcessor {
                             continue;
                         }
                         targetList.add(targetSlot);
+                        targetExpressions.add(targetSlot);
                         targetNodes.add(scan);
                         ctx.addJoinToTargetMap(join, targetSlot.getExprId());
                         ctx.setTargetsOnScanNode(scan, targetSlot);
@@ -626,7 +629,8 @@ public class RuntimeFilterGenerator extends PlanPostProcessor {
                     // build multi-target runtime filter
                     // since always on different join, set the expr_order as 0
                     RuntimeFilter filter = new RuntimeFilter(generator.getNextId(),
-                            equalTo.right(), targetList, type, 0, join, buildSideNdv, cteNode);
+                            equalTo.right(), targetList, targetExpressions, type, 0, join, buildSideNdv, true,
+                            cteNode);
                     targetNodes.forEach(node -> node.addAppliedRuntimeFilter(filter));
                     for (Slot slot : targetList) {
                         ctx.setTargetExprIdToFilter(slot.getExprId(), filter);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/AbstractPhysicalPlan.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/AbstractPhysicalPlan.java
index 6a19abcc8fc..5d8d4046f57 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/AbstractPhysicalPlan.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/AbstractPhysicalPlan.java
@@ -126,19 +126,20 @@ public abstract class AbstractPhysicalPlan extends AbstractPlan implements Physi
                 // however, RF(B.b->A.a2) is implied by RF(B.a->A.a1) and A.a1=A.a2
                 // we skip RF(B.b->A.a2)
                 this.addAppliedRuntimeFilter(filter);
-                filter.addTargetSlot(scanSlot, scan);
-                filter.addTargetExpression(scanSlot);
+                filter.addTargetSlot(scanSlot, probeExpr, scan);
                 ctx.addJoinToTargetMap(builderNode, scanSlot.getExprId());
                 ctx.setTargetExprIdToFilter(scanSlot.getExprId(), filter);
                 ctx.setTargetsOnScanNode(ctx.getAliasTransferPair((NamedExpression) probeExpr).first, scanSlot);
             }
         } else {
             filter = new RuntimeFilter(generator.getNextId(),
-                    src, ImmutableList.of(scanSlot), type, exprOrder, builderNode, buildSideNdv, scan);
+                    src, ImmutableList.of(scanSlot), ImmutableList.of(probeExpr),
+                    type, exprOrder, builderNode, buildSideNdv,
+                    !context.getStatementContext().isHasUnknownColStats(), scan);
             this.addAppliedRuntimeFilter(filter);
             ctx.addJoinToTargetMap(builderNode, scanSlot.getExprId());
             ctx.setTargetExprIdToFilter(scanSlot.getExprId(), filter);
-            ctx.setTargetsOnScanNode(ctx.getAliasTransferPair((NamedExpression) probeExpr).first, scanSlot);
+            ctx.setTargetsOnScanNode(ctx.getAliasTransferPair((NamedExpression) probeSlot).first, scanSlot);
             ctx.setRuntimeFilterIdentityToFilter(src, type, builderNode, filter);
         }
         return true;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalProject.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalProject.java
index 18d4f36204c..8cdfedbfdd3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalProject.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalProject.java
@@ -28,6 +28,7 @@ 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.SlotReference;
 import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.nereids.trees.plans.PlanType;
 import org.apache.doris.nereids.trees.plans.algebra.Project;
@@ -198,7 +199,15 @@ public class PhysicalProject<CHILD_TYPE extends Plan> extends PhysicalUnary<CHIL
             if (!RuntimeFilterGenerator.checkPushDownPreconditionsForRelation(this, scan)) {
                 return false;
             }
-
+            if (probeExpr instanceof SlotReference) {
+                for (NamedExpression namedExpression : projects) {
+                    if (namedExpression instanceof Alias
+                            && namedExpression.getExprId() == ((SlotReference) probeExpr).getExprId()) {
+                        probeExpr = ((Alias) namedExpression).child();
+                        break;
+                    }
+                }
+            }
             AbstractPhysicalPlan child = (AbstractPhysicalPlan) child(0);
             return child.pushDownRuntimeFilter(context, generator, builderNode,
                     src, probeExpr, type, buildSideNdv, exprOrder);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/RuntimeFilter.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/RuntimeFilter.java
index 3a3b01daecd..f9b269ec30b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/RuntimeFilter.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/RuntimeFilter.java
@@ -23,7 +23,6 @@ import org.apache.doris.planner.RuntimeFilterId;
 import org.apache.doris.thrift.TMinMaxRuntimeFilterType;
 import org.apache.doris.thrift.TRuntimeFilterType;
 
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
 import java.util.List;
@@ -52,22 +51,27 @@ public class RuntimeFilter {
 
     private final List<PhysicalRelation> targetScans = Lists.newArrayList();
 
+    private final boolean bloomFilterSizeCalculatedByNdv;
+
     /**
      * constructor
      */
-    public RuntimeFilter(RuntimeFilterId id, Expression src, List<Slot> targets, TRuntimeFilterType type,
-            int exprOrder, AbstractPhysicalJoin builderNode, long buildSideNdv,
+    public RuntimeFilter(RuntimeFilterId id, Expression src, List<Slot> targets, List<Expression> targetExpressions,
+                         TRuntimeFilterType type, int exprOrder, AbstractPhysicalJoin builderNode, long buildSideNdv,
+                         boolean bloomFilterSizeCalculatedByNdv,
                          PhysicalRelation scan) {
-        this(id, src, targets, ImmutableList.copyOf(targets), type, exprOrder,
-                builderNode, false, buildSideNdv, TMinMaxRuntimeFilterType.MIN_MAX, scan);
+        this(id, src, targets, targetExpressions, type, exprOrder,
+                builderNode, false, buildSideNdv, bloomFilterSizeCalculatedByNdv,
+                TMinMaxRuntimeFilterType.MIN_MAX, scan);
     }
 
     public RuntimeFilter(RuntimeFilterId id, Expression src, List<Slot> targets, List<Expression> targetExpressions,
                          TRuntimeFilterType type, int exprOrder, AbstractPhysicalJoin builderNode,
-                         boolean bitmapFilterNotIn, long buildSideNdv,
+                         boolean bitmapFilterNotIn, long buildSideNdv, boolean bloomFilterSizeCalculatedByNdv,
                          PhysicalRelation scan) {
         this(id, src, targets, targetExpressions, type, exprOrder,
-                builderNode, bitmapFilterNotIn, buildSideNdv, TMinMaxRuntimeFilterType.MIN_MAX, scan);
+                builderNode, bitmapFilterNotIn, buildSideNdv, bloomFilterSizeCalculatedByNdv,
+                TMinMaxRuntimeFilterType.MIN_MAX, scan);
     }
 
     /**
@@ -75,7 +79,8 @@ public class RuntimeFilter {
      */
     public RuntimeFilter(RuntimeFilterId id, Expression src, List<Slot> targets, List<Expression> targetExpressions,
                          TRuntimeFilterType type, int exprOrder, AbstractPhysicalJoin builderNode,
-                         boolean bitmapFilterNotIn, long buildSideNdv, TMinMaxRuntimeFilterType tMinMaxType,
+                         boolean bitmapFilterNotIn, long buildSideNdv, boolean bloomFilterSizeCalculatedByNdv,
+                         TMinMaxRuntimeFilterType tMinMaxType,
                          PhysicalRelation scan) {
         this.id = id;
         this.srcSlot = src;
@@ -85,6 +90,7 @@ public class RuntimeFilter {
         this.exprOrder = exprOrder;
         this.builderNode = builderNode;
         this.bitmapFilterNotIn = bitmapFilterNotIn;
+        this.bloomFilterSizeCalculatedByNdv = bloomFilterSizeCalculatedByNdv;
         this.buildSideNdv = buildSideNdv <= 0 ? -1L : buildSideNdv;
         this.tMinMaxType = tMinMaxType;
         builderNode.addRuntimeFilter(this);
@@ -99,10 +105,6 @@ public class RuntimeFilter {
         return srcSlot;
     }
 
-    public List<Slot> getTargetExprs() {
-        return targetSlots;
-    }
-
     public RuntimeFilterId getId() {
         return id;
     }
@@ -131,7 +133,8 @@ public class RuntimeFilter {
         return buildSideNdv;
     }
 
-    public void addTargetSlot(Slot target, PhysicalRelation scan) {
+    public void addTargetSlot(Slot target, Expression targetExpression, PhysicalRelation scan) {
+        targetExpressions.add(targetExpression);
         targetSlots.add(target);
         targetScans.add(scan);
     }
@@ -140,10 +143,6 @@ public class RuntimeFilter {
         return targetSlots;
     }
 
-    public void addTargetExpression(Expression targetExpr) {
-        targetExpressions.add(targetExpr);
-    }
-
     public List<PhysicalRelation> getTargetScans() {
         return targetScans;
     }
@@ -156,7 +155,7 @@ public class RuntimeFilter {
     public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("RF").append(id.asInt())
-                .append("[").append(getSrcExpr()).append("->").append(targetSlots)
+                .append("[").append(getSrcExpr()).append("->").append(targetExpressions)
                 .append("(ndv/size = ").append(buildSideNdv).append("/")
                 .append(org.apache.doris.planner.RuntimeFilter.expectRuntimeFilterSize(buildSideNdv))
                 .append(")");
@@ -171,8 +170,12 @@ public class RuntimeFilter {
         StringBuilder sb = new StringBuilder();
         sb.append("RF").append(id.asInt())
                 .append(" ").append(getSrcExpr().toSql()).append("->[").append(
-                        targetSlots.stream().map(slot -> slot.getName()).collect(Collectors.joining(",")))
+                        targetExpressions.stream().map(expr -> expr.toSql()).collect(Collectors.joining(",")))
                 .append("]");
         return sb.toString();
     }
+
+    public boolean isBloomFilterSizeCalculatedByNdv() {
+        return bloomFilterSizeCalculatedByNdv;
+    }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
index 7a2d9fc27d5..5c8bd80c78f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/ExpressionUtils.java
@@ -51,6 +51,7 @@ import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionRewri
 import org.apache.doris.nereids.trees.expressions.visitor.DefaultExpressionVisitor;
 import org.apache.doris.nereids.trees.plans.Plan;
 import org.apache.doris.nereids.trees.plans.visitor.ExpressionLineageReplacer;
+import org.apache.doris.nereids.types.coercion.NumericType;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
@@ -659,6 +660,25 @@ public class ExpressionUtils {
         return expression;
     }
 
+    /**
+     * the expressions can be used as runtime filter targets
+     */
+    public static Expression getSingleNumericSlotOrExpressionCoveredByCast(Expression expression) {
+        if (expression.getInputSlots().size() == 1) {
+            Slot slot = expression.getInputSlots().iterator().next();
+            if (slot.getDataType() instanceof NumericType) {
+                return expression.getInputSlots().iterator().next();
+            }
+        }
+        // for other datatype, only support cast.
+        // example: T1 join T2 on subStr(T1.a, 1,4) = subStr(T2.a, 1,4)
+        // the cost of subStr is too high, and hence we do not generate RF subStr(T2.a, 1,4)->subStr(T1.a, 1,4)
+        while (expression instanceof Cast) {
+            expression = ((Cast) expression).child();
+        }
+        return expression;
+    }
+
     /**
      * To check whether a slot is constant after passing through a filter
      */
diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/RuntimeFilter.java b/fe/fe-core/src/main/java/org/apache/doris/planner/RuntimeFilter.java
index 646a07221a7..58d4d3eabe3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/RuntimeFilter.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/RuntimeFilter.java
@@ -112,6 +112,8 @@ public final class RuntimeFilter {
 
     private TMinMaxRuntimeFilterType tMinMaxRuntimeFilterType;
 
+    private boolean bloomFilterSizeCalculatedByNdv = false;
+
     /**
      * Internal representation of a runtime filter target.
      */
@@ -244,6 +246,7 @@ public final class RuntimeFilter {
             tFilter.setMinMaxType(tMinMaxRuntimeFilterType);
         }
         tFilter.setOptRemoteRf(optRemoteRf);
+        tFilter.setBloomFilterSizeCalculatedByNdv(bloomFilterSizeCalculatedByNdv);
         return tFilter;
     }
 
@@ -741,4 +744,13 @@ public final class RuntimeFilter {
         }
         return filterStr.toString();
     }
+
+
+    public boolean isBloomFilterSizeCalculatedByNdv() {
+        return bloomFilterSizeCalculatedByNdv;
+    }
+
+    public void setBloomFilterSizeCalculatedByNdv(boolean bloomFilterSizeCalculatedByNdv) {
+        this.bloomFilterSizeCalculatedByNdv = bloomFilterSizeCalculatedByNdv;
+    }
 }
diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/RuntimeFilterTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/RuntimeFilterTest.java
index e8753d1e5ce..ce647427d21 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/RuntimeFilterTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/postprocess/RuntimeFilterTest.java
@@ -309,7 +309,7 @@ public class RuntimeFilterTest extends SSBTestBase {
         for (RuntimeFilter filter : filters) {
             Assertions.assertTrue(colNames.contains(Pair.of(
                     filter.getSrcExpr().toSql(),
-                    filter.getTargetExprs().get(0).getName())));
+                    filter.getTargetSlots().get(0).getName())));
         }
     }
 
@@ -318,7 +318,7 @@ public class RuntimeFilterTest extends SSBTestBase {
         for (RuntimeFilter filter : filters) {
             srcTargets.contains(Pair.of(
                     filter.getSrcExpr().toSql(),
-                    filter.getTargetExprs().stream().collect(Collectors.toSet())
+                    filter.getTargetSlots().stream().collect(Collectors.toSet())
             ));
         }
     }
diff --git a/gensrc/thrift/PlanNodes.thrift b/gensrc/thrift/PlanNodes.thrift
index 2f45f355b1e..b73d7a9351d 100644
--- a/gensrc/thrift/PlanNodes.thrift
+++ b/gensrc/thrift/PlanNodes.thrift
@@ -1177,6 +1177,11 @@ struct TRuntimeFilterDesc {
   
   // for min/max rf
   13: optional TMinMaxRuntimeFilterType min_max_type;
+
+  // true, if bloom filter size is calculated by ndv
+  // if bloom_filter_size_calculated_by_ndv=false, BE could calculate filter size according to the actural row count, and 
+  // ignore bloom_filter_size_bytes
+  14: optional bool bloom_filter_size_calculated_by_ndv;
 }
 
 


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