Skip to content

Commit 47e3b18

Browse files
qw4990ti-chi-bot
authored andcommitted
This is an automated cherry-pick of pingcap#45587
Signed-off-by: ti-chi-bot <[email protected]>
1 parent 4c91878 commit 47e3b18

File tree

2 files changed

+69
-61
lines changed

2 files changed

+69
-61
lines changed

planner/core/exhaust_physical_plans.go

Lines changed: 66 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,61 +1967,87 @@ func filterIndexJoinBySessionVars(sc sessionctx.Context, indexJoins []PhysicalPl
19671967
return indexJoins
19681968
}
19691969

1970-
// tryToGetIndexJoin will get index join by hints. If we can generate a valid index join by hint, the second return value
1971-
// will be true, which means we force to choose this index join. Otherwise we will select a join algorithm with min-cost.
1972-
func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJoins []PhysicalPlan, canForced bool) {
1973-
inljRightOuter := (p.preferJoinType & preferLeftAsINLJInner) > 0
1974-
inljLeftOuter := (p.preferJoinType & preferRightAsINLJInner) > 0
1975-
hasINLJHint := inljLeftOuter || inljRightOuter
1970+
func (p *LogicalJoin) preferAny(joinFlags ...uint) bool {
1971+
for _, flag := range joinFlags {
1972+
if p.preferJoinType&flag > 0 {
1973+
return true
1974+
}
1975+
}
1976+
return false
1977+
}
19761978

1977-
inlhjRightOuter := (p.preferJoinType & preferLeftAsINLHJInner) > 0
1978-
inlhjLeftOuter := (p.preferJoinType & preferRightAsINLHJInner) > 0
1979-
hasINLHJHint := inlhjLeftOuter || inlhjRightOuter
1979+
// satisfyIndexJoinHint returns whether this join plan can satisfy current index join hints.
1980+
func (p *LogicalJoin) satisfyIndexJoinHint(join PhysicalPlan) bool {
1981+
const left, right = 0, 1
1982+
const indexJoin, indexHashJoin, indexMergeJoin = 0, 1, 2
1983+
var innerSide, innerIdx, joinMethod int
1984+
switch ij := join.(type) {
1985+
case *PhysicalIndexJoin:
1986+
innerIdx = ij.getInnerChildIdx()
1987+
joinMethod = indexJoin
1988+
case *PhysicalIndexHashJoin:
1989+
innerIdx = ij.getInnerChildIdx()
1990+
joinMethod = indexHashJoin
1991+
case *PhysicalIndexMergeJoin:
1992+
innerIdx = ij.getInnerChildIdx()
1993+
joinMethod = indexMergeJoin
1994+
default:
1995+
return false
1996+
}
1997+
innerSide = left
1998+
if innerIdx == 1 {
1999+
innerSide = right
2000+
}
19802001

1981-
inlmjRightOuter := (p.preferJoinType & preferLeftAsINLMJInner) > 0
1982-
inlmjLeftOuter := (p.preferJoinType & preferRightAsINLMJInner) > 0
1983-
hasINLMJHint := inlmjLeftOuter || inlmjRightOuter
2002+
if (p.preferAny(preferLeftAsINLJInner) && innerSide == left && joinMethod == indexJoin) ||
2003+
(p.preferAny(preferRightAsINLJInner) && innerSide == right && joinMethod == indexJoin) ||
2004+
(p.preferAny(preferLeftAsINLHJInner) && innerSide == left && joinMethod == indexHashJoin) ||
2005+
(p.preferAny(preferRightAsINLHJInner) && innerSide == right && joinMethod == indexHashJoin) ||
2006+
(p.preferAny(preferLeftAsINLMJInner) && innerSide == left && joinMethod == indexMergeJoin) ||
2007+
(p.preferAny(preferRightAsINLMJInner) && innerSide == right && joinMethod == indexMergeJoin) {
2008+
return true
2009+
}
2010+
return false
2011+
}
19842012

1985-
forceLeftOuter := inljLeftOuter || inlhjLeftOuter || inlmjLeftOuter
1986-
forceRightOuter := inljRightOuter || inlhjRightOuter || inlmjRightOuter
2013+
// tryToGetIndexJoin will get index join by hints. If we can generate a valid index join by hint, the second return value
2014+
// will be true, which means we force to choose this index join. Otherwise we will select a join algorithm with min-cost.
2015+
func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJoins []PhysicalPlan, canForced bool) {
2016+
forceLeftOuter := p.preferAny(preferRightAsINLJInner, preferRightAsINLHJInner, preferRightAsINLMJInner) // left as outer == right as inner
2017+
forceRightOuter := p.preferAny(preferLeftAsINLJInner, preferLeftAsINLHJInner, preferLeftAsINLMJInner) // right as outer == left as inner
19872018
needForced := forceLeftOuter || forceRightOuter
19882019

19892020
defer func() {
1990-
// refine error message
2021+
// Print warning message if any hints cannot work.
19912022
// If the required property is not empty, we will enforce it and try the hint again.
19922023
// So we only need to generate warning message when the property is empty.
19932024
if !canForced && needForced && prop.IsSortItemEmpty() {
19942025
// Construct warning message prefix.
2026+
var indexJoinTables, indexHashJoinTables, indexMergeJoinTables []hintTableInfo
2027+
if p.hintInfo != nil {
2028+
t := p.hintInfo.indexNestedLoopJoinTables
2029+
indexJoinTables, indexHashJoinTables, indexMergeJoinTables = t.inljTables, t.inlhjTables, t.inlmjTables
2030+
}
19952031
var errMsg string
19962032
switch {
1997-
case hasINLJHint:
1998-
errMsg = "Optimizer Hint INL_JOIN or TIDB_INLJ is inapplicable"
1999-
case hasINLHJHint:
2000-
errMsg = "Optimizer Hint INL_HASH_JOIN is inapplicable"
2001-
case hasINLMJHint:
2002-
errMsg = "Optimizer Hint INL_MERGE_JOIN is inapplicable"
2003-
}
2004-
if p.hintInfo != nil && p.preferJoinType > 0 {
2005-
t := p.hintInfo.indexNestedLoopJoinTables
2006-
switch {
2007-
case len(t.inljTables) != 0 && ((p.preferJoinType&preferLeftAsINLJInner > 0) || (p.preferJoinType&preferRightAsINLJInner > 0)):
2008-
errMsg = fmt.Sprintf("Optimizer Hint %s or %s is inapplicable",
2009-
restore2JoinHint(HintINLJ, t.inljTables), restore2JoinHint(TiDBIndexNestedLoopJoin, t.inljTables))
2010-
case len(t.inlhjTables) != 0 && ((p.preferJoinType&preferLeftAsINLHJInner > 0) || (p.preferJoinType&preferRightAsINLHJInner > 0)):
2011-
errMsg = fmt.Sprintf("Optimizer Hint %s is inapplicable", restore2JoinHint(HintINLHJ, t.inlhjTables))
2012-
case len(t.inlmjTables) != 0 && ((p.preferJoinType&preferLeftAsINLMJInner > 0) || (p.preferJoinType&preferRightAsINLMJInner > 0)):
2013-
errMsg = fmt.Sprintf("Optimizer Hint %s is inapplicable", restore2JoinHint(HintINLMJ, t.inlmjTables))
2014-
}
2033+
case p.preferAny(preferLeftAsINLJInner, preferRightAsINLJInner): // prefer index join
2034+
errMsg = fmt.Sprintf("Optimizer Hint %s or %s is inapplicable", restore2JoinHint(HintINLJ, indexJoinTables), restore2JoinHint(TiDBIndexNestedLoopJoin, indexJoinTables))
2035+
case p.preferAny(preferLeftAsINLHJInner, preferRightAsINLHJInner): // prefer index hash join
2036+
errMsg = fmt.Sprintf("Optimizer Hint %s is inapplicable", restore2JoinHint(HintINLHJ, indexHashJoinTables))
2037+
case p.preferAny(preferLeftAsINLMJInner, preferRightAsINLMJInner): // prefer index merge join
2038+
errMsg = fmt.Sprintf("Optimizer Hint %s is inapplicable", restore2JoinHint(HintINLMJ, indexMergeJoinTables))
20152039
}
2016-
20172040
// Append inapplicable reason.
20182041
if len(p.EqualConditions) == 0 {
20192042
errMsg += " without column equal ON condition"
20202043
}
2021-
20222044
// Generate warning message to client.
2045+
<<<<<<< HEAD
20232046
warning := ErrInternal.GenWithStack(errMsg)
20242047
p.ctx.GetSessionVars().StmtCtx.AppendWarning(warning)
2048+
=======
2049+
p.SCtx().GetSessionVars().StmtCtx.AppendWarning(ErrInternal.GenWithStack(errMsg))
2050+
>>>>>>> 64be9ec4c0c (planner: refine `tryToGetIndexJoin` (#45587))
20252051
}
20262052
}()
20272053

@@ -2042,19 +2068,8 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ
20422068
allLeftOuterJoins = p.getIndexJoinByOuterIdx(prop, 0)
20432069
forcedLeftOuterJoins = make([]PhysicalPlan, 0, len(allLeftOuterJoins))
20442070
for _, j := range allLeftOuterJoins {
2045-
switch j.(type) {
2046-
case *PhysicalIndexJoin:
2047-
if inljLeftOuter {
2048-
forcedLeftOuterJoins = append(forcedLeftOuterJoins, j)
2049-
}
2050-
case *PhysicalIndexHashJoin:
2051-
if inlhjLeftOuter {
2052-
forcedLeftOuterJoins = append(forcedLeftOuterJoins, j)
2053-
}
2054-
case *PhysicalIndexMergeJoin:
2055-
if inlmjLeftOuter {
2056-
forcedLeftOuterJoins = append(forcedLeftOuterJoins, j)
2057-
}
2071+
if p.satisfyIndexJoinHint(j) {
2072+
forcedLeftOuterJoins = append(forcedLeftOuterJoins, j)
20582073
}
20592074
}
20602075
switch {
@@ -2064,23 +2079,13 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ
20642079
return forcedLeftOuterJoins, true
20652080
}
20662081
}
2082+
20672083
if supportRightOuter {
20682084
allRightOuterJoins = p.getIndexJoinByOuterIdx(prop, 1)
20692085
forcedRightOuterJoins = make([]PhysicalPlan, 0, len(allRightOuterJoins))
20702086
for _, j := range allRightOuterJoins {
2071-
switch j.(type) {
2072-
case *PhysicalIndexJoin:
2073-
if inljRightOuter {
2074-
forcedRightOuterJoins = append(forcedRightOuterJoins, j)
2075-
}
2076-
case *PhysicalIndexHashJoin:
2077-
if inlhjRightOuter {
2078-
forcedRightOuterJoins = append(forcedRightOuterJoins, j)
2079-
}
2080-
case *PhysicalIndexMergeJoin:
2081-
if inlmjRightOuter {
2082-
forcedRightOuterJoins = append(forcedRightOuterJoins, j)
2083-
}
2087+
if p.satisfyIndexJoinHint(j) {
2088+
forcedRightOuterJoins = append(forcedRightOuterJoins, j)
20842089
}
20852090
}
20862091
switch {

planner/core/planbuilder.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ func restore2TableHint(hintTables ...hintTableInfo) string {
340340
}
341341

342342
func restore2JoinHint(hintType string, hintTables []hintTableInfo) string {
343+
if len(hintTables) == 0 {
344+
return strings.ToUpper(hintType)
345+
}
343346
buffer := bytes.NewBufferString("/*+ ")
344347
buffer.WriteString(strings.ToUpper(hintType))
345348
buffer.WriteString("(")

0 commit comments

Comments
 (0)