@@ -1967,61 +1967,87 @@ func filterIndexJoinBySessionVars(sc sessionctx.Context, indexJoins []PhysicalPl
1967
1967
return indexJoins
1968
1968
}
1969
1969
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
+ }
1976
1978
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
+ }
1980
2001
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
+ }
1984
2012
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
1987
2018
needForced := forceLeftOuter || forceRightOuter
1988
2019
1989
2020
defer func () {
1990
- // refine error message
2021
+ // Print warning message if any hints cannot work.
1991
2022
// If the required property is not empty, we will enforce it and try the hint again.
1992
2023
// So we only need to generate warning message when the property is empty.
1993
2024
if ! canForced && needForced && prop .IsSortItemEmpty () {
1994
2025
// 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
+ }
1995
2031
var errMsg string
1996
2032
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 ))
2015
2039
}
2016
-
2017
2040
// Append inapplicable reason.
2018
2041
if len (p .EqualConditions ) == 0 {
2019
2042
errMsg += " without column equal ON condition"
2020
2043
}
2021
-
2022
2044
// Generate warning message to client.
2045
+ << << << < HEAD
2023
2046
warning := ErrInternal .GenWithStack (errMsg )
2024
2047
p .ctx .GetSessionVars ().StmtCtx .AppendWarning (warning )
2048
+ == == == =
2049
+ p .SCtx ().GetSessionVars ().StmtCtx .AppendWarning (ErrInternal .GenWithStack (errMsg ))
2050
+ >> >> >> > 64 be9ec4c0c (planner : refine `tryToGetIndexJoin` (#45587 ))
2025
2051
}
2026
2052
}()
2027
2053
@@ -2042,19 +2068,8 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ
2042
2068
allLeftOuterJoins = p .getIndexJoinByOuterIdx (prop , 0 )
2043
2069
forcedLeftOuterJoins = make ([]PhysicalPlan , 0 , len (allLeftOuterJoins ))
2044
2070
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 )
2058
2073
}
2059
2074
}
2060
2075
switch {
@@ -2064,23 +2079,13 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ
2064
2079
return forcedLeftOuterJoins , true
2065
2080
}
2066
2081
}
2082
+
2067
2083
if supportRightOuter {
2068
2084
allRightOuterJoins = p .getIndexJoinByOuterIdx (prop , 1 )
2069
2085
forcedRightOuterJoins = make ([]PhysicalPlan , 0 , len (allRightOuterJoins ))
2070
2086
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 )
2084
2089
}
2085
2090
}
2086
2091
switch {
0 commit comments