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 <engle...@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-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org