From 21f526f69b994be6740a3cdbd064da05b50e7893 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Thu, 27 Jul 2023 16:59:35 +0800 Subject: [PATCH 1/7] fixup --- planner/core/exhaust_physical_plans.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/planner/core/exhaust_physical_plans.go b/planner/core/exhaust_physical_plans.go index 77cc854995465..f7d9a44d275d8 100644 --- a/planner/core/exhaust_physical_plans.go +++ b/planner/core/exhaust_physical_plans.go @@ -1979,7 +1979,7 @@ func (p *LogicalJoin) preferAny(joinFlags ...uint) bool { } // satisfyIndexJoinHint returns whether this join plan can satisfy current index join hints. -func (p *LogicalJoin) satisfyIndexJoinHint(join PhysicalPlan) bool { +func (p *LogicalJoin) satisfyForceIndexJoinHint(join PhysicalPlan) bool { const left, right = 0, 1 const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 var innerSide, innerIdx, joinMethod int @@ -2065,7 +2065,7 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ allLeftOuterJoins = p.getIndexJoinByOuterIdx(prop, 0) forcedLeftOuterJoins = make([]PhysicalPlan, 0, len(allLeftOuterJoins)) for _, j := range allLeftOuterJoins { - if p.satisfyIndexJoinHint(j) { + if p.satisfyForceIndexJoinHint(j) { forcedLeftOuterJoins = append(forcedLeftOuterJoins, j) } } @@ -2081,7 +2081,7 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ allRightOuterJoins = p.getIndexJoinByOuterIdx(prop, 1) forcedRightOuterJoins = make([]PhysicalPlan, 0, len(allRightOuterJoins)) for _, j := range allRightOuterJoins { - if p.satisfyIndexJoinHint(j) { + if p.satisfyForceIndexJoinHint(j) { forcedRightOuterJoins = append(forcedRightOuterJoins, j) } } From 9922aa244c68bcb4edf915edd0c9d56db114f106 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Thu, 27 Jul 2023 17:13:36 +0800 Subject: [PATCH 2/7] fixup --- planner/core/exhaust_physical_plans.go | 103 ++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/planner/core/exhaust_physical_plans.go b/planner/core/exhaust_physical_plans.go index f7d9a44d275d8..8d520d148861c 100644 --- a/planner/core/exhaust_physical_plans.go +++ b/planner/core/exhaust_physical_plans.go @@ -1978,6 +1978,28 @@ func (p *LogicalJoin) preferAny(joinFlags ...uint) bool { return false } +func (p *LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, outerSide, joinMethod int) { + const left, right = 0, 1 + const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 + var innerIdx int + switch ij := join.(type) { + case *PhysicalIndexJoin: + innerIdx = ij.getInnerChildIdx() + joinMethod = indexJoin + case *PhysicalIndexHashJoin: + innerIdx = ij.getInnerChildIdx() + joinMethod = indexHashJoin + case *PhysicalIndexMergeJoin: + innerIdx = ij.getInnerChildIdx() + joinMethod = indexMergeJoin + } + innerSide, outerSide = left, right + if innerIdx == 1 { + innerSide, outerSide = right, left + } + return +} + // satisfyIndexJoinHint returns whether this join plan can satisfy current index join hints. func (p *LogicalJoin) satisfyForceIndexJoinHint(join PhysicalPlan) bool { const left, right = 0, 1 @@ -2012,9 +2034,88 @@ func (p *LogicalJoin) satisfyForceIndexJoinHint(join PhysicalPlan) bool { return false } +func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJoins []PhysicalPlan, canForced bool) { + // supportLeftOuter and supportRightOuter indicates whether this type of join + // supports the left side or right side to be the outer side. + var supportLeftOuter, supportRightOuter bool + switch p.JoinType { + case SemiJoin, AntiSemiJoin, LeftOuterSemiJoin, AntiLeftOuterSemiJoin, LeftOuterJoin: + supportLeftOuter = true + case RightOuterJoin: + supportRightOuter = true + case InnerJoin: + supportLeftOuter, supportRightOuter = true, true + } + candidates := make([]PhysicalPlan, 0, 2) + if supportLeftOuter { + candidates = append(candidates, p.getIndexJoinByOuterIdx(prop, 0)...) + } + if supportRightOuter { + candidates = append(candidates, p.getIndexJoinByOuterIdx(prop, 1)...) + } + candidates, canForced = p.handleForceIndexJoinHints(prop, candidates) + if canForced { + return candidates, canForced + } + return filterIndexJoinBySessionVars(p.SCtx(), candidates), false +} + +func (p *LogicalJoin) handleForceIndexJoinHints(prop *property.PhysicalProperty, candidates []PhysicalPlan) (indexJoins []PhysicalPlan, canForced bool) { + if !p.preferAny(preferRightAsINLJInner, preferRightAsINLHJInner, preferRightAsINLMJInner, + preferLeftAsINLJInner, preferLeftAsINLHJInner, preferLeftAsINLMJInner) { + return candidates, false // no force index join hints + } + + const left, right = 0, 1 + const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 + forced := make([]PhysicalPlan, 0, len(candidates)) + for _, candidate := range candidates { + innerSide, _, joinMethod := p.getIndexJoinSideAndMethod(candidate) + if (p.preferAny(preferLeftAsINLJInner) && innerSide == left && joinMethod == indexJoin) || + (p.preferAny(preferRightAsINLJInner) && innerSide == right && joinMethod == indexJoin) || + (p.preferAny(preferLeftAsINLHJInner) && innerSide == left && joinMethod == indexHashJoin) || + (p.preferAny(preferRightAsINLHJInner) && innerSide == right && joinMethod == indexHashJoin) || + (p.preferAny(preferLeftAsINLMJInner) && innerSide == left && joinMethod == indexMergeJoin) || + (p.preferAny(preferRightAsINLMJInner) && innerSide == right && joinMethod == indexMergeJoin) { + forced = append(forced, candidate) + } + } + + if len(forced) > 0 { + return forced, true + } + // Cannot find any valid index join plan with these force hints. + // Print warning message if any hints cannot work. + // If the required property is not empty, we will enforce it and try the hint again. + // So we only need to generate warning message when the property is empty. + if prop.IsSortItemEmpty() { + var indexJoinTables, indexHashJoinTables, indexMergeJoinTables []hintTableInfo + if p.hintInfo != nil { + t := p.hintInfo.indexNestedLoopJoinTables + indexJoinTables, indexHashJoinTables, indexMergeJoinTables = t.inljTables, t.inlhjTables, t.inlmjTables + } + var errMsg string + switch { + case p.preferAny(preferLeftAsINLJInner, preferRightAsINLJInner): // prefer index join + errMsg = fmt.Sprintf("Optimizer Hint %s or %s is inapplicable", restore2JoinHint(HintINLJ, indexJoinTables), restore2JoinHint(TiDBIndexNestedLoopJoin, indexJoinTables)) + case p.preferAny(preferLeftAsINLHJInner, preferRightAsINLHJInner): // prefer index hash join + errMsg = fmt.Sprintf("Optimizer Hint %s is inapplicable", restore2JoinHint(HintINLHJ, indexHashJoinTables)) + case p.preferAny(preferLeftAsINLMJInner, preferRightAsINLMJInner): // prefer index merge join + errMsg = fmt.Sprintf("Optimizer Hint %s is inapplicable", restore2JoinHint(HintINLMJ, indexMergeJoinTables)) + } + // Append inapplicable reason. + if len(p.EqualConditions) == 0 { + errMsg += " without column equal ON condition" + } + // Generate warning message to client. + p.SCtx().GetSessionVars().StmtCtx.AppendWarning(ErrInternal.GenWithStack(errMsg)) + } + return candidates, false +} + // tryToGetIndexJoin will get index join by hints. If we can generate a valid index join by hint, the second return value // will be true, which means we force to choose this index join. Otherwise we will select a join algorithm with min-cost. -func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJoins []PhysicalPlan, canForced bool) { +func (p *LogicalJoin) tryToGetIndexJoinX(prop *property.PhysicalProperty) (indexJoins []PhysicalPlan, canForced bool) { forceLeftOuter := p.preferAny(preferRightAsINLJInner, preferRightAsINLHJInner, preferRightAsINLMJInner) // left as outer == right as inner forceRightOuter := p.preferAny(preferLeftAsINLJInner, preferLeftAsINLHJInner, preferLeftAsINLMJInner) // right as outer == left as inner needForced := forceLeftOuter || forceRightOuter From 322c9e93b8c96d3ec877d63b592b5ad0db995730 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Thu, 27 Jul 2023 17:20:21 +0800 Subject: [PATCH 3/7] fixup --- planner/core/exhaust_physical_plans.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/core/exhaust_physical_plans.go b/planner/core/exhaust_physical_plans.go index 8d520d148861c..d056515e83609 100644 --- a/planner/core/exhaust_physical_plans.go +++ b/planner/core/exhaust_physical_plans.go @@ -1978,7 +1978,7 @@ func (p *LogicalJoin) preferAny(joinFlags ...uint) bool { return false } -func (p *LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, outerSide, joinMethod int) { +func (_ *LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, outerSide, joinMethod int) { const left, right = 0, 1 const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 var innerIdx int From 0be7987933dbc7101d3d05167fa9d04f7f943b5f Mon Sep 17 00:00:00 2001 From: qw4990 Date: Thu, 27 Jul 2023 17:27:15 +0800 Subject: [PATCH 4/7] fixup --- planner/core/exhaust_physical_plans.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/core/exhaust_physical_plans.go b/planner/core/exhaust_physical_plans.go index d056515e83609..307812e383484 100644 --- a/planner/core/exhaust_physical_plans.go +++ b/planner/core/exhaust_physical_plans.go @@ -1978,7 +1978,7 @@ func (p *LogicalJoin) preferAny(joinFlags ...uint) bool { return false } -func (_ *LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, outerSide, joinMethod int) { +func (*LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, outerSide, joinMethod int) { const left, right = 0, 1 const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 var innerIdx int From f7031d490d2057520234d80f58286cf641471138 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Thu, 27 Jul 2023 18:37:46 +0800 Subject: [PATCH 5/7] fixup --- planner/core/exhaust_physical_plans.go | 135 ++----------------------- 1 file changed, 8 insertions(+), 127 deletions(-) diff --git a/planner/core/exhaust_physical_plans.go b/planner/core/exhaust_physical_plans.go index 307812e383484..93fe3b17e162a 100644 --- a/planner/core/exhaust_physical_plans.go +++ b/planner/core/exhaust_physical_plans.go @@ -1978,7 +1978,7 @@ func (p *LogicalJoin) preferAny(joinFlags ...uint) bool { return false } -func (*LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, outerSide, joinMethod int) { +func (*LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, joinMethod int) { const left, right = 0, 1 const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 var innerIdx int @@ -1993,47 +1993,14 @@ func (*LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, out innerIdx = ij.getInnerChildIdx() joinMethod = indexMergeJoin } - innerSide, outerSide = left, right - if innerIdx == 1 { - innerSide, outerSide = right, left - } - return -} - -// satisfyIndexJoinHint returns whether this join plan can satisfy current index join hints. -func (p *LogicalJoin) satisfyForceIndexJoinHint(join PhysicalPlan) bool { - const left, right = 0, 1 - const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 - var innerSide, innerIdx, joinMethod int - switch ij := join.(type) { - case *PhysicalIndexJoin: - innerIdx = ij.getInnerChildIdx() - joinMethod = indexJoin - case *PhysicalIndexHashJoin: - innerIdx = ij.getInnerChildIdx() - joinMethod = indexHashJoin - case *PhysicalIndexMergeJoin: - innerIdx = ij.getInnerChildIdx() - joinMethod = indexMergeJoin - default: - return false - } innerSide = left if innerIdx == 1 { innerSide = right } - - if (p.preferAny(preferLeftAsINLJInner) && innerSide == left && joinMethod == indexJoin) || - (p.preferAny(preferRightAsINLJInner) && innerSide == right && joinMethod == indexJoin) || - (p.preferAny(preferLeftAsINLHJInner) && innerSide == left && joinMethod == indexHashJoin) || - (p.preferAny(preferRightAsINLHJInner) && innerSide == right && joinMethod == indexHashJoin) || - (p.preferAny(preferLeftAsINLMJInner) && innerSide == left && joinMethod == indexMergeJoin) || - (p.preferAny(preferRightAsINLMJInner) && innerSide == right && joinMethod == indexMergeJoin) { - return true - } - return false + return } +// tryToGetIndexJoin returns all available index join plans, and the second returned value indicates whether this plan is enforced by hints. func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJoins []PhysicalPlan, canForced bool) { // supportLeftOuter and supportRightOuter indicates whether this type of join // supports the left side or right side to be the outer side. @@ -2053,6 +2020,9 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ if supportRightOuter { candidates = append(candidates, p.getIndexJoinByOuterIdx(prop, 1)...) } + + // handle hints and variables about index join. + // the priority is: force hints like TIDB_INLJ > filter hints like NO_INDEX_JOIN > variables. candidates, canForced = p.handleForceIndexJoinHints(prop, candidates) if canForced { return candidates, canForced @@ -2060,6 +2030,7 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ return filterIndexJoinBySessionVars(p.SCtx(), candidates), false } +// handleForceIndexJoinHints handles the force index join hints and returns all plans that can satisfy the hints. func (p *LogicalJoin) handleForceIndexJoinHints(prop *property.PhysicalProperty, candidates []PhysicalPlan) (indexJoins []PhysicalPlan, canForced bool) { if !p.preferAny(preferRightAsINLJInner, preferRightAsINLHJInner, preferRightAsINLMJInner, preferLeftAsINLJInner, preferLeftAsINLHJInner, preferLeftAsINLMJInner) { @@ -2070,7 +2041,7 @@ func (p *LogicalJoin) handleForceIndexJoinHints(prop *property.PhysicalProperty, const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 forced := make([]PhysicalPlan, 0, len(candidates)) for _, candidate := range candidates { - innerSide, _, joinMethod := p.getIndexJoinSideAndMethod(candidate) + innerSide, joinMethod := p.getIndexJoinSideAndMethod(candidate) if (p.preferAny(preferLeftAsINLJInner) && innerSide == left && joinMethod == indexJoin) || (p.preferAny(preferRightAsINLJInner) && innerSide == right && joinMethod == indexJoin) || (p.preferAny(preferLeftAsINLHJInner) && innerSide == left && joinMethod == indexHashJoin) || @@ -2113,96 +2084,6 @@ func (p *LogicalJoin) handleForceIndexJoinHints(prop *property.PhysicalProperty, return candidates, false } -// tryToGetIndexJoin will get index join by hints. If we can generate a valid index join by hint, the second return value -// will be true, which means we force to choose this index join. Otherwise we will select a join algorithm with min-cost. -func (p *LogicalJoin) tryToGetIndexJoinX(prop *property.PhysicalProperty) (indexJoins []PhysicalPlan, canForced bool) { - forceLeftOuter := p.preferAny(preferRightAsINLJInner, preferRightAsINLHJInner, preferRightAsINLMJInner) // left as outer == right as inner - forceRightOuter := p.preferAny(preferLeftAsINLJInner, preferLeftAsINLHJInner, preferLeftAsINLMJInner) // right as outer == left as inner - needForced := forceLeftOuter || forceRightOuter - - defer func() { - // Print warning message if any hints cannot work. - // If the required property is not empty, we will enforce it and try the hint again. - // So we only need to generate warning message when the property is empty. - if !canForced && needForced && prop.IsSortItemEmpty() { - // Construct warning message prefix. - var indexJoinTables, indexHashJoinTables, indexMergeJoinTables []hintTableInfo - if p.hintInfo != nil { - t := p.hintInfo.indexNestedLoopJoinTables - indexJoinTables, indexHashJoinTables, indexMergeJoinTables = t.inljTables, t.inlhjTables, t.inlmjTables - } - var errMsg string - switch { - case p.preferAny(preferLeftAsINLJInner, preferRightAsINLJInner): // prefer index join - errMsg = fmt.Sprintf("Optimizer Hint %s or %s is inapplicable", restore2JoinHint(HintINLJ, indexJoinTables), restore2JoinHint(TiDBIndexNestedLoopJoin, indexJoinTables)) - case p.preferAny(preferLeftAsINLHJInner, preferRightAsINLHJInner): // prefer index hash join - errMsg = fmt.Sprintf("Optimizer Hint %s is inapplicable", restore2JoinHint(HintINLHJ, indexHashJoinTables)) - case p.preferAny(preferLeftAsINLMJInner, preferRightAsINLMJInner): // prefer index merge join - errMsg = fmt.Sprintf("Optimizer Hint %s is inapplicable", restore2JoinHint(HintINLMJ, indexMergeJoinTables)) - } - // Append inapplicable reason. - if len(p.EqualConditions) == 0 { - errMsg += " without column equal ON condition" - } - // Generate warning message to client. - p.SCtx().GetSessionVars().StmtCtx.AppendWarning(ErrInternal.GenWithStack(errMsg)) - } - }() - - // supportLeftOuter and supportRightOuter indicates whether this type of join - // supports the left side or right side to be the outer side. - var supportLeftOuter, supportRightOuter bool - switch p.JoinType { - case SemiJoin, AntiSemiJoin, LeftOuterSemiJoin, AntiLeftOuterSemiJoin, LeftOuterJoin: - supportLeftOuter = true - case RightOuterJoin: - supportRightOuter = true - case InnerJoin: - supportLeftOuter, supportRightOuter = true, true - } - - var allLeftOuterJoins, allRightOuterJoins, forcedLeftOuterJoins, forcedRightOuterJoins []PhysicalPlan - if supportLeftOuter { - allLeftOuterJoins = p.getIndexJoinByOuterIdx(prop, 0) - forcedLeftOuterJoins = make([]PhysicalPlan, 0, len(allLeftOuterJoins)) - for _, j := range allLeftOuterJoins { - if p.satisfyForceIndexJoinHint(j) { - forcedLeftOuterJoins = append(forcedLeftOuterJoins, j) - } - } - switch { - case len(forcedLeftOuterJoins) == 0 && !supportRightOuter: - return filterIndexJoinBySessionVars(p.SCtx(), allLeftOuterJoins), false - case len(forcedLeftOuterJoins) != 0 && (!supportRightOuter || (forceLeftOuter && !forceRightOuter)): - return forcedLeftOuterJoins, true - } - } - - if supportRightOuter { - allRightOuterJoins = p.getIndexJoinByOuterIdx(prop, 1) - forcedRightOuterJoins = make([]PhysicalPlan, 0, len(allRightOuterJoins)) - for _, j := range allRightOuterJoins { - if p.satisfyForceIndexJoinHint(j) { - forcedRightOuterJoins = append(forcedRightOuterJoins, j) - } - } - switch { - case len(forcedRightOuterJoins) == 0 && !supportLeftOuter: - return filterIndexJoinBySessionVars(p.SCtx(), allRightOuterJoins), false - case len(forcedRightOuterJoins) != 0 && (!supportLeftOuter || (forceRightOuter && !forceLeftOuter)): - return forcedRightOuterJoins, true - } - } - - canForceLeft := len(forcedLeftOuterJoins) != 0 && forceLeftOuter - canForceRight := len(forcedRightOuterJoins) != 0 && forceRightOuter - canForced = canForceLeft || canForceRight - if canForced { - return append(forcedLeftOuterJoins, forcedRightOuterJoins...), true - } - return filterIndexJoinBySessionVars(p.SCtx(), append(allLeftOuterJoins, allRightOuterJoins...)), false -} - func checkChildFitBC(p Plan) bool { if p.StatsInfo().HistColl == nil { return p.SCtx().GetSessionVars().BroadcastJoinThresholdCount == -1 || p.StatsInfo().Count() < p.SCtx().GetSessionVars().BroadcastJoinThresholdCount From 5f80a465f4e6bfa8236cdc55fd4b49c780e59192 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Thu, 27 Jul 2023 18:52:30 +0800 Subject: [PATCH 6/7] address comments --- planner/core/exhaust_physical_plans.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/planner/core/exhaust_physical_plans.go b/planner/core/exhaust_physical_plans.go index 93fe3b17e162a..2d40148783606 100644 --- a/planner/core/exhaust_physical_plans.go +++ b/planner/core/exhaust_physical_plans.go @@ -1978,7 +1978,7 @@ func (p *LogicalJoin) preferAny(joinFlags ...uint) bool { return false } -func (*LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, joinMethod int) { +func (*LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, joinMethod int, ok bool) { const left, right = 0, 1 const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 var innerIdx int @@ -1992,7 +1992,10 @@ func (*LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, joi case *PhysicalIndexMergeJoin: innerIdx = ij.getInnerChildIdx() joinMethod = indexMergeJoin + default: + return 0, 0, false } + ok = true innerSide = left if innerIdx == 1 { innerSide = right @@ -2041,7 +2044,10 @@ func (p *LogicalJoin) handleForceIndexJoinHints(prop *property.PhysicalProperty, const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 forced := make([]PhysicalPlan, 0, len(candidates)) for _, candidate := range candidates { - innerSide, joinMethod := p.getIndexJoinSideAndMethod(candidate) + innerSide, joinMethod, ok := p.getIndexJoinSideAndMethod(candidate) + if !ok { + continue + } if (p.preferAny(preferLeftAsINLJInner) && innerSide == left && joinMethod == indexJoin) || (p.preferAny(preferRightAsINLJInner) && innerSide == right && joinMethod == indexJoin) || (p.preferAny(preferLeftAsINLHJInner) && innerSide == left && joinMethod == indexHashJoin) || From 7b6514d151d0379469c4d46108b9ed7389c646f2 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Fri, 28 Jul 2023 10:16:04 +0800 Subject: [PATCH 7/7] address comments --- planner/core/exhaust_physical_plans.go | 35 ++++++++++++++------------ 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/planner/core/exhaust_physical_plans.go b/planner/core/exhaust_physical_plans.go index 2d40148783606..f984f2e12b2cc 100644 --- a/planner/core/exhaust_physical_plans.go +++ b/planner/core/exhaust_physical_plans.go @@ -1978,27 +1978,33 @@ func (p *LogicalJoin) preferAny(joinFlags ...uint) bool { return false } +const ( + joinLeft = 0 + joinRight = 1 + indexJoinMethod = 0 + indexHashJoinMethod = 1 + indexMergeJoinMethod = 2 +) + func (*LogicalJoin) getIndexJoinSideAndMethod(join PhysicalPlan) (innerSide, joinMethod int, ok bool) { - const left, right = 0, 1 - const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 var innerIdx int switch ij := join.(type) { case *PhysicalIndexJoin: innerIdx = ij.getInnerChildIdx() - joinMethod = indexJoin + joinMethod = indexJoinMethod case *PhysicalIndexHashJoin: innerIdx = ij.getInnerChildIdx() - joinMethod = indexHashJoin + joinMethod = indexHashJoinMethod case *PhysicalIndexMergeJoin: innerIdx = ij.getInnerChildIdx() - joinMethod = indexMergeJoin + joinMethod = indexMergeJoinMethod default: return 0, 0, false } ok = true - innerSide = left + innerSide = joinLeft if innerIdx == 1 { - innerSide = right + innerSide = joinRight } return } @@ -2039,21 +2045,18 @@ func (p *LogicalJoin) handleForceIndexJoinHints(prop *property.PhysicalProperty, preferLeftAsINLJInner, preferLeftAsINLHJInner, preferLeftAsINLMJInner) { return candidates, false // no force index join hints } - - const left, right = 0, 1 - const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2 forced := make([]PhysicalPlan, 0, len(candidates)) for _, candidate := range candidates { innerSide, joinMethod, ok := p.getIndexJoinSideAndMethod(candidate) if !ok { continue } - if (p.preferAny(preferLeftAsINLJInner) && innerSide == left && joinMethod == indexJoin) || - (p.preferAny(preferRightAsINLJInner) && innerSide == right && joinMethod == indexJoin) || - (p.preferAny(preferLeftAsINLHJInner) && innerSide == left && joinMethod == indexHashJoin) || - (p.preferAny(preferRightAsINLHJInner) && innerSide == right && joinMethod == indexHashJoin) || - (p.preferAny(preferLeftAsINLMJInner) && innerSide == left && joinMethod == indexMergeJoin) || - (p.preferAny(preferRightAsINLMJInner) && innerSide == right && joinMethod == indexMergeJoin) { + if (p.preferAny(preferLeftAsINLJInner) && innerSide == joinLeft && joinMethod == indexJoinMethod) || + (p.preferAny(preferRightAsINLJInner) && innerSide == joinRight && joinMethod == indexJoinMethod) || + (p.preferAny(preferLeftAsINLHJInner) && innerSide == joinLeft && joinMethod == indexHashJoinMethod) || + (p.preferAny(preferRightAsINLHJInner) && innerSide == joinRight && joinMethod == indexHashJoinMethod) || + (p.preferAny(preferLeftAsINLMJInner) && innerSide == joinLeft && joinMethod == indexMergeJoinMethod) || + (p.preferAny(preferRightAsINLMJInner) && innerSide == joinRight && joinMethod == indexMergeJoinMethod) { forced = append(forced, candidate) } }