This is an automated email from the ASF dual-hosted git repository.
englefly 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 59efebce3b5 [opt](nereids) estimate join cost when col stats are not
available (#26086)
59efebce3b5 is described below
commit 59efebce3b5193eea5a7ff97f149ae43d0624f1a
Author: minghong <[email protected]>
AuthorDate: Fri Nov 10 16:13:53 2023 +0800
[opt](nereids) estimate join cost when col stats are not available (#26086)
no stats left zigzag
---
.../org/apache/doris/nereids/cost/CostModelV1.java | 21 ----------------
.../jobs/cascades/OptimizeGroupExpressionJob.java | 5 ++++
.../org/apache/doris/nereids/rules/RuleSet.java | 12 +++++++++
.../rules/exploration/join/InnerJoinLAsscom.java | 29 +++++++++++++++++-----
.../exploration/join/InnerJoinLAsscomProject.java | 10 ++++++--
.../rules/exploration/join/JoinCommute.java | 14 ++++++++++-
.../join/SemiJoinSemiJoinTransposeProject.java | 2 +-
.../apache/doris/nereids/stats/JoinEstimation.java | 2 +-
.../java/org/apache/doris/qe/SessionVariable.java | 12 +++++++++
.../joinorder/hypergraph/GraphSimplifierTest.java | 8 +++---
.../org/apache/doris/nereids/memo/RankTest.java | 2 +-
11 files changed, 80 insertions(+), 37 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/cost/CostModelV1.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/cost/CostModelV1.java
index 72baa7deaf0..44af6122819 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/cost/CostModelV1.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/cost/CostModelV1.java
@@ -293,27 +293,12 @@ class CostModelV1 extends PlanVisitor<Cost, PlanContext> {
// use totalInstanceNumber to the power of 2 as the default
factor value
buildSideFactor = Math.pow(totalInstanceNumber, 0.5);
}
- // TODO: since the outputs rows may expand a lot, penalty on it
will cause bc never be chosen.
- // will refine this in next generation cost model.
- if (!context.isStatsReliable()) {
- // forbid broadcast join when stats is unknown
- return CostV1.of(context.getSessionVariable(), rightRowCount *
buildSideFactor + 1 / leftRowCount,
- rightRowCount,
- 0
- );
- }
return CostV1.of(context.getSessionVariable(),
leftRowCount + rightRowCount * buildSideFactor +
outputRowCount * probeSideFactor,
rightRowCount,
0
);
}
- if (!context.isStatsReliable()) {
- return CostV1.of(context.getSessionVariable(),
- rightRowCount + 1 / leftRowCount,
- rightRowCount,
- 0);
- }
return CostV1.of(context.getSessionVariable(), leftRowCount +
rightRowCount + outputRowCount,
rightRowCount,
0
@@ -328,12 +313,6 @@ class CostModelV1 extends PlanVisitor<Cost, PlanContext> {
Preconditions.checkState(context.arity() == 2);
Statistics leftStatistics = context.getChildStatistics(0);
Statistics rightStatistics = context.getChildStatistics(1);
- if (!context.isStatsReliable()) {
- return CostV1.of(context.getSessionVariable(),
- rightStatistics.getRowCount() + 1 /
leftStatistics.getRowCount(),
- rightStatistics.getRowCount(),
- 0);
- }
return CostV1.of(context.getSessionVariable(),
leftStatistics.getRowCount() * rightStatistics.getRowCount(),
rightStatistics.getRowCount(),
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/OptimizeGroupExpressionJob.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/OptimizeGroupExpressionJob.java
index 178818e660c..38c0c4484bc 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/OptimizeGroupExpressionJob.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/cascades/OptimizeGroupExpressionJob.java
@@ -71,6 +71,9 @@ public class OptimizeGroupExpressionJob extends Job {
boolean isOtherJoinReorder =
context.getCascadesContext().getStatementContext().isOtherJoinReorder();
boolean isEnableBushyTree =
context.getCascadesContext().getConnectContext().getSessionVariable()
.isEnableBushyTree();
+ boolean isLeftZigZagTree =
context.getCascadesContext().getConnectContext()
+ .getSessionVariable().isEnableLeftZigZag()
+ || (groupExpression.getOwnerGroup() != null &&
!groupExpression.getOwnerGroup().isStatsReliable());
int joinNumBushyTree = context.getCascadesContext().getConnectContext()
.getSessionVariable().getMaxJoinNumBushyTree();
if (isDisableJoinReorder) {
@@ -81,6 +84,8 @@ public class OptimizeGroupExpressionJob extends Job {
} else {
return Collections.emptyList();
}
+ } else if (isLeftZigZagTree) {
+ return getRuleSet().getLeftZigZagTreeJoinReorder();
} else if (isEnableBushyTree) {
return getRuleSet().getBushyTreeJoinReorder();
} else if
(context.getCascadesContext().getStatementContext().getMaxNAryInnerJoin() <=
joinNumBushyTree) {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java
index b8bb9e8c46e..80163663184 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/RuleSet.java
@@ -180,6 +180,14 @@ public class RuleSet {
.add(new
LogicalDeferMaterializeResultSinkToPhysicalDeferMaterializeResultSink())
.build();
+ // left-zig-zag tree is used when column stats are not available.
+ public static final List<Rule> LEFT_ZIG_ZAG_TREE_JOIN_REORDER =
planRuleFactories()
+ .add(JoinCommute.LEFT_ZIG_ZAG)
+ .add(InnerJoinLAsscom.LEFT_ZIG_ZAG)
+ .add(InnerJoinLAsscomProject.LEFT_ZIG_ZAG)
+ .addAll(OTHER_REORDER_RULES)
+ .build();
+
public static final List<Rule> ZIG_ZAG_TREE_JOIN_REORDER =
planRuleFactories()
.add(JoinCommute.ZIG_ZAG)
.add(InnerJoinLAsscom.INSTANCE)
@@ -220,6 +228,10 @@ public class RuleSet {
return ZIG_ZAG_TREE_JOIN_REORDER_RULES;
}
+ public List<Rule> getLeftZigZagTreeJoinReorder() {
+ return LEFT_ZIG_ZAG_TREE_JOIN_REORDER;
+ }
+
public List<Rule> getBushyTreeJoinReorder() {
return BUSHY_TREE_JOIN_REORDER_RULES;
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/InnerJoinLAsscom.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/InnerJoinLAsscom.java
index d92aede5bb9..f256bff004d 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/InnerJoinLAsscom.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/InnerJoinLAsscom.java
@@ -36,7 +36,13 @@ import java.util.stream.Collectors;
* Rule for change inner join LAsscom (associative and commutive).
*/
public class InnerJoinLAsscom extends OneExplorationRuleFactory {
- public static final InnerJoinLAsscom INSTANCE = new InnerJoinLAsscom();
+ public static final InnerJoinLAsscom INSTANCE = new
InnerJoinLAsscom(false);
+ public static final InnerJoinLAsscom LEFT_ZIG_ZAG = new
InnerJoinLAsscom(true);
+ private boolean leftZigZag = false;
+
+ public InnerJoinLAsscom(boolean leftZigZag) {
+ this.leftZigZag = leftZigZag;
+ }
/*
* topJoin newTopJoin
@@ -48,7 +54,7 @@ public class InnerJoinLAsscom extends
OneExplorationRuleFactory {
@Override
public Rule build() {
return innerLogicalJoin(innerLogicalJoin(), group())
- .when(topJoin -> checkReorder(topJoin, topJoin.left()))
+ .when(topJoin -> checkReorder(topJoin, topJoin.left(),
leftZigZag))
.whenNot(join -> join.hasJoinHint() ||
join.left().hasJoinHint())
.whenNot(join -> join.isMarkJoin() || join.left().isMarkJoin())
.then(topJoin -> {
@@ -85,11 +91,22 @@ public class InnerJoinLAsscom extends
OneExplorationRuleFactory {
}).toRule(RuleType.LOGICAL_INNER_JOIN_LASSCOM);
}
+ /**
+ * trigger rule condition
+ */
public static boolean checkReorder(LogicalJoin<? extends Plan, GroupPlan>
topJoin,
- LogicalJoin<GroupPlan, GroupPlan> bottomJoin) {
- return !bottomJoin.getJoinReorderContext().hasCommuteZigZag()
- && !topJoin.getJoinReorderContext().hasLAsscom()
- && (!bottomJoin.isMarkJoin() && !topJoin.isMarkJoin());
+ LogicalJoin<GroupPlan, GroupPlan> bottomJoin, boolean leftZigZag) {
+ if (leftZigZag) {
+ double bRows =
bottomJoin.right().getGroup().getStatistics().getRowCount();
+ double cRows =
topJoin.right().getGroup().getStatistics().getRowCount();
+ return bRows < cRows &&
!bottomJoin.getJoinReorderContext().hasCommuteZigZag()
+ && !topJoin.getJoinReorderContext().hasLAsscom()
+ && (!bottomJoin.isMarkJoin() && !topJoin.isMarkJoin());
+ } else {
+ return !bottomJoin.getJoinReorderContext().hasCommuteZigZag()
+ && !topJoin.getJoinReorderContext().hasLAsscom()
+ && (!bottomJoin.isMarkJoin() && !topJoin.isMarkJoin());
+ }
}
/**
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/InnerJoinLAsscomProject.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/InnerJoinLAsscomProject.java
index 2ca9c815915..297ec9d76e7 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/InnerJoinLAsscomProject.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/InnerJoinLAsscomProject.java
@@ -40,8 +40,13 @@ import java.util.stream.Collectors;
* Rule for change inner join LAsscom (associative and commutive).
*/
public class InnerJoinLAsscomProject extends OneExplorationRuleFactory {
- public static final InnerJoinLAsscomProject INSTANCE = new
InnerJoinLAsscomProject();
+ public static final InnerJoinLAsscomProject INSTANCE = new
InnerJoinLAsscomProject(false);
+ public static final InnerJoinLAsscomProject LEFT_ZIG_ZAG = new
InnerJoinLAsscomProject(true);
+ private final boolean enableLeftZigZag;
+ public InnerJoinLAsscomProject(boolean enableLeftZigZag) {
+ this.enableLeftZigZag = enableLeftZigZag;
+ }
/*
* topJoin newTopJoin
* / \ / \
@@ -51,10 +56,11 @@ public class InnerJoinLAsscomProject extends
OneExplorationRuleFactory {
* / \ / \
* A B A C
*/
+
@Override
public Rule build() {
return innerLogicalJoin(logicalProject(innerLogicalJoin()), group())
- .when(topJoin -> InnerJoinLAsscom.checkReorder(topJoin,
topJoin.left().child()))
+ .when(topJoin -> InnerJoinLAsscom.checkReorder(topJoin,
topJoin.left().child(), enableLeftZigZag))
.whenNot(join -> join.hasJoinHint() ||
join.left().child().hasJoinHint())
.whenNot(join -> join.isMarkJoin() ||
join.left().child().isMarkJoin())
.when(join -> join.left().isAllSlots())
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/JoinCommute.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/JoinCommute.java
index f4c56fabd50..d6df03e1c0b 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/JoinCommute.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/JoinCommute.java
@@ -38,6 +38,7 @@ import java.util.List;
public class JoinCommute extends OneExplorationRuleFactory {
public static final JoinCommute LEFT_DEEP = new
JoinCommute(SwapType.LEFT_DEEP, false);
+ public static final JoinCommute LEFT_ZIG_ZAG = new
JoinCommute(SwapType.LEFT_ZIG_ZAG, false);
public static final JoinCommute ZIG_ZAG = new
JoinCommute(SwapType.ZIG_ZAG, false);
public static final JoinCommute BUSHY = new JoinCommute(SwapType.BUSHY,
false);
public static final JoinCommute NON_INNER = new
JoinCommute(SwapType.BUSHY, true);
@@ -73,7 +74,8 @@ public class JoinCommute extends OneExplorationRuleFactory {
}
enum SwapType {
- LEFT_DEEP, ZIG_ZAG, BUSHY
+ LEFT_DEEP, ZIG_ZAG, BUSHY,
+ LEFT_ZIG_ZAG
}
/**
@@ -88,6 +90,12 @@ public class JoinCommute extends OneExplorationRuleFactory {
return false;
}
+ if (swapType == SwapType.LEFT_ZIG_ZAG) {
+ double leftRows =
join.left().getGroup().getStatistics().getRowCount();
+ double rightRows =
join.right().getGroup().getStatistics().getRowCount();
+ return leftRows < rightRows && isZigZagJoin(join);
+ }
+
return true;
}
@@ -101,6 +109,10 @@ public class JoinCommute extends OneExplorationRuleFactory
{
return containJoin(join.left()) || containJoin(join.right());
}
+ public static boolean isZigZagJoin(LogicalJoin<GroupPlan, GroupPlan> join)
{
+ return !containJoin(join.left()) || !containJoin(join.right());
+ }
+
private static boolean containJoin(GroupPlan groupPlan) {
// TODO: tmp way to judge containJoin
List<Slot> output = groupPlan.getOutput();
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinSemiJoinTransposeProject.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinSemiJoinTransposeProject.java
index 0db1c800871..13e9c7cd461 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinSemiJoinTransposeProject.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/exploration/join/SemiJoinSemiJoinTransposeProject.java
@@ -53,7 +53,7 @@ public class SemiJoinSemiJoinTransposeProject extends
OneExplorationRuleFactory
public Rule build() {
return logicalJoin(logicalProject(logicalJoin()), group())
.when(this::typeChecker)
- .when(topSemi -> InnerJoinLAsscom.checkReorder(topSemi,
topSemi.left().child()))
+ .when(topSemi -> InnerJoinLAsscom.checkReorder(topSemi,
topSemi.left().child(), false))
.whenNot(join -> join.hasJoinHint() ||
join.left().child().hasJoinHint())
.whenNot(join -> join.isMarkJoin() ||
join.left().child().isMarkJoin())
.when(join -> join.left().isAllSlots())
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/JoinEstimation.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/JoinEstimation.java
index 261d4385cef..3b7797439f3 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/JoinEstimation.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/stats/JoinEstimation.java
@@ -171,7 +171,7 @@ public class JoinEstimation {
private static Statistics estimateInnerJoin(Statistics leftStats,
Statistics rightStats, Join join) {
if (hashJoinConditionContainsUnknownColumnStats(leftStats, rightStats,
join)) {
- double rowCount = leftStats.getRowCount() +
rightStats.getRowCount();
+ double rowCount = Math.max(leftStats.getRowCount(),
rightStats.getRowCount());
rowCount = Math.max(1, rowCount);
return new StatisticsBuilder()
.setRowCount(rowCount)
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
index 7a4cef6e40b..b4c117874ff 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java
@@ -245,6 +245,7 @@ public class SessionVariable implements Serializable,
Writable {
public static final String ENABLE_DPHYP_OPTIMIZER =
"enable_dphyp_optimizer";
+ public static final String ENABLE_LEFT_ZIG_ZAG = "enable_left_zig_zag";
public static final String NTH_OPTIMIZED_PLAN = "nth_optimized_plan";
public static final String ENABLE_NEREIDS_PLANNER =
"enable_nereids_planner";
@@ -909,6 +910,17 @@ public class SessionVariable implements Serializable,
Writable {
@VariableMgr.VarAttr(name = NTH_OPTIMIZED_PLAN)
private int nthOptimizedPlan = 1;
+ public boolean isEnableLeftZigZag() {
+ return enableLeftZigZag;
+ }
+
+ public void setEnableLeftZigZag(boolean enableLeftZigZag) {
+ this.enableLeftZigZag = enableLeftZigZag;
+ }
+
+ @VariableMgr.VarAttr(name = ENABLE_LEFT_ZIG_ZAG)
+ private boolean enableLeftZigZag = false;
+
/**
* as the new optimizer is not mature yet, use this var
* to control whether to use new optimizer, remove it when
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/GraphSimplifierTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/GraphSimplifierTest.java
index 402cc1b64da..a1d44658dbc 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/GraphSimplifierTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/jobs/joinorder/hypergraph/GraphSimplifierTest.java
@@ -89,10 +89,10 @@ class GraphSimplifierTest {
.add(Pair.of(17L, 2L)) // 04 - 1
.add(Pair.of(17L, 4L)) // 04 - 2
.add(Pair.of(17L, 8L)) // 04 - 3
- .add(Pair.of(25L, 2L)) // 034 - 1
- .add(Pair.of(25L, 4L)) // 034 - 2
- .add(Pair.of(29L, 2L)) // 0234 - 1
- .build(); // 0-4-3-2-1 : big left deep tree
+ .add(Pair.of(19L, 8L)) // 041 - 2
+ .add(Pair.of(21L, 2L)) // 042 - 1
+ .add(Pair.of(23L, 8L)) // 0134 - 2
+ .build(); // 0-4-3-1-2 : big left deep tree
for (Pair<Long, Long> step : steps) {
if (!graphSimplifier.applySimplificationStep()) {
break;
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/memo/RankTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/memo/RankTest.java
index ba0f4bd26c0..e3571395e47 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/nereids/memo/RankTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/memo/RankTest.java
@@ -55,7 +55,7 @@ class RankTest extends TestWithFeService {
shape.add(memo.unrank(memo.rank(i + 1).first).shape(""));
}
System.out.println(shape);
- Assertions.assertEquals(4, shape.size());
+ Assertions.assertEquals(1, shape.size());
Assertions.assertEquals(bestPlan.shape(""),
memo.unrank(memo.rank(1).first).shape(""));
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]