@@ -1864,58 +1864,80 @@ func filterIndexJoinBySessionVars(sc sessionctx.Context, indexJoins []PhysicalPl
1864
1864
return indexJoins
1865
1865
}
1866
1866
1867
- // tryToGetIndexJoin will get index join by hints. If we can generate a valid index join by hint, the second return value
1868
- // will be true, which means we force to choose this index join. Otherwise we will select a join algorithm with min-cost.
1869
- func (p * LogicalJoin ) tryToGetIndexJoin (prop * property.PhysicalProperty ) (indexJoins []PhysicalPlan , canForced bool ) {
1870
- inljRightOuter := (p .preferJoinType & preferLeftAsINLJInner ) > 0
1871
- inljLeftOuter := (p .preferJoinType & preferRightAsINLJInner ) > 0
1872
- hasINLJHint := inljLeftOuter || inljRightOuter
1867
+ func (p * LogicalJoin ) preferAny (joinFlags ... uint ) bool {
1868
+ for _ , flag := range joinFlags {
1869
+ if p .preferJoinType & flag > 0 {
1870
+ return true
1871
+ }
1872
+ }
1873
+ return false
1874
+ }
1873
1875
1874
- inlhjRightOuter := (p .preferJoinType & preferLeftAsINLHJInner ) > 0
1875
- inlhjLeftOuter := (p .preferJoinType & preferRightAsINLHJInner ) > 0
1876
- hasINLHJHint := inlhjLeftOuter || inlhjRightOuter
1876
+ // satisfyIndexJoinHint returns whether this join plan can satisfy current index join hints.
1877
+ func (p * LogicalJoin ) satisfyIndexJoinHint (join PhysicalPlan ) bool {
1878
+ const left , right = 0 , 1
1879
+ const indexJoin , indexHashJoin , indexMergeJoin = 0 , 1 , 2
1880
+ var innerSide , innerIdx , joinMethod int
1881
+ switch ij := join .(type ) {
1882
+ case * PhysicalIndexJoin :
1883
+ innerIdx = ij .getInnerChildIdx ()
1884
+ joinMethod = indexJoin
1885
+ case * PhysicalIndexHashJoin :
1886
+ innerIdx = ij .getInnerChildIdx ()
1887
+ joinMethod = indexHashJoin
1888
+ case * PhysicalIndexMergeJoin :
1889
+ innerIdx = ij .getInnerChildIdx ()
1890
+ joinMethod = indexMergeJoin
1891
+ default :
1892
+ return false
1893
+ }
1894
+ innerSide = left
1895
+ if innerIdx == 1 {
1896
+ innerSide = right
1897
+ }
1877
1898
1878
- inlmjRightOuter := (p .preferJoinType & preferLeftAsINLMJInner ) > 0
1879
- inlmjLeftOuter := (p .preferJoinType & preferRightAsINLMJInner ) > 0
1880
- hasINLMJHint := inlmjLeftOuter || inlmjRightOuter
1899
+ if (p .preferAny (preferLeftAsINLJInner ) && innerSide == left && joinMethod == indexJoin ) ||
1900
+ (p .preferAny (preferRightAsINLJInner ) && innerSide == right && joinMethod == indexJoin ) ||
1901
+ (p .preferAny (preferLeftAsINLHJInner ) && innerSide == left && joinMethod == indexHashJoin ) ||
1902
+ (p .preferAny (preferRightAsINLHJInner ) && innerSide == right && joinMethod == indexHashJoin ) ||
1903
+ (p .preferAny (preferLeftAsINLMJInner ) && innerSide == left && joinMethod == indexMergeJoin ) ||
1904
+ (p .preferAny (preferRightAsINLMJInner ) && innerSide == right && joinMethod == indexMergeJoin ) {
1905
+ return true
1906
+ }
1907
+ return false
1908
+ }
1881
1909
1882
- forceLeftOuter := inljLeftOuter || inlhjLeftOuter || inlmjLeftOuter
1883
- forceRightOuter := inljRightOuter || inlhjRightOuter || inlmjRightOuter
1910
+ // tryToGetIndexJoin will get index join by hints. If we can generate a valid index join by hint, the second return value
1911
+ // will be true, which means we force to choose this index join. Otherwise we will select a join algorithm with min-cost.
1912
+ func (p * LogicalJoin ) tryToGetIndexJoin (prop * property.PhysicalProperty ) (indexJoins []PhysicalPlan , canForced bool ) {
1913
+ forceLeftOuter := p .preferAny (preferRightAsINLJInner , preferRightAsINLHJInner , preferRightAsINLMJInner ) // left as outer == right as inner
1914
+ forceRightOuter := p .preferAny (preferLeftAsINLJInner , preferLeftAsINLHJInner , preferLeftAsINLMJInner ) // right as outer == left as inner
1884
1915
needForced := forceLeftOuter || forceRightOuter
1885
1916
1886
1917
defer func () {
1887
- // refine error message
1918
+ // Print warning message if any hints cannot work.
1888
1919
// If the required property is not empty, we will enforce it and try the hint again.
1889
1920
// So we only need to generate warning message when the property is empty.
1890
1921
if ! canForced && needForced && prop .IsSortItemEmpty () {
1891
1922
// Construct warning message prefix.
1923
+ var indexJoinTables , indexHashJoinTables , indexMergeJoinTables []hintTableInfo
1924
+ if p .hintInfo != nil {
1925
+ t := p .hintInfo .indexNestedLoopJoinTables
1926
+ indexJoinTables , indexHashJoinTables , indexMergeJoinTables = t .inljTables , t .inlhjTables , t .inlmjTables
1927
+ }
1892
1928
var errMsg string
1893
1929
switch {
1894
- case hasINLJHint :
1895
- errMsg = "Optimizer Hint INL_JOIN or TIDB_INLJ is inapplicable"
1896
- case hasINLHJHint :
1897
- errMsg = "Optimizer Hint INL_HASH_JOIN is inapplicable"
1898
- case hasINLMJHint :
1899
- errMsg = "Optimizer Hint INL_MERGE_JOIN is inapplicable"
1900
- }
1901
- if p .hintInfo != nil && p .preferJoinType > 0 {
1902
- t := p .hintInfo .indexNestedLoopJoinTables
1903
- switch {
1904
- case len (t .inljTables ) != 0 :
1905
- errMsg = fmt .Sprintf ("Optimizer Hint %s or %s is inapplicable" ,
1906
- restore2JoinHint (HintINLJ , t .inljTables ), restore2JoinHint (TiDBIndexNestedLoopJoin , t .inljTables ))
1907
- case len (t .inlhjTables ) != 0 :
1908
- errMsg = fmt .Sprintf ("Optimizer Hint %s is inapplicable" , restore2JoinHint (HintINLHJ , t .inlhjTables ))
1909
- case len (t .inlmjTables ) != 0 :
1910
- errMsg = fmt .Sprintf ("Optimizer Hint %s is inapplicable" , restore2JoinHint (HintINLMJ , t .inlmjTables ))
1911
- }
1930
+ case p .preferAny (preferLeftAsINLJInner , preferRightAsINLJInner ): // prefer index join
1931
+ errMsg = fmt .Sprintf ("Optimizer Hint %s or %s is inapplicable" , restore2JoinHint (HintINLJ , indexJoinTables ), restore2JoinHint (TiDBIndexNestedLoopJoin , indexJoinTables ))
1932
+ case p .preferAny (preferLeftAsINLHJInner , preferRightAsINLHJInner ): // prefer index hash join
1933
+ errMsg = fmt .Sprintf ("Optimizer Hint %s is inapplicable" , restore2JoinHint (HintINLHJ , indexHashJoinTables ))
1934
+ case p .preferAny (preferLeftAsINLMJInner , preferRightAsINLMJInner ): // prefer index merge join
1935
+ errMsg = fmt .Sprintf ("Optimizer Hint %s is inapplicable" , restore2JoinHint (HintINLMJ , indexMergeJoinTables ))
1912
1936
}
1913
-
1914
1937
// Append inapplicable reason.
1915
1938
if len (p .EqualConditions ) == 0 {
1916
1939
errMsg += " without column equal ON condition"
1917
1940
}
1918
-
1919
1941
// Generate warning message to client.
1920
1942
warning := ErrInternal .GenWithStack (errMsg )
1921
1943
p .ctx .GetSessionVars ().StmtCtx .AppendWarning (warning )
@@ -1939,19 +1961,8 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ
1939
1961
allLeftOuterJoins = p .getIndexJoinByOuterIdx (prop , 0 )
1940
1962
forcedLeftOuterJoins = make ([]PhysicalPlan , 0 , len (allLeftOuterJoins ))
1941
1963
for _ , j := range allLeftOuterJoins {
1942
- switch j .(type ) {
1943
- case * PhysicalIndexJoin :
1944
- if inljLeftOuter {
1945
- forcedLeftOuterJoins = append (forcedLeftOuterJoins , j )
1946
- }
1947
- case * PhysicalIndexHashJoin :
1948
- if inlhjLeftOuter {
1949
- forcedLeftOuterJoins = append (forcedLeftOuterJoins , j )
1950
- }
1951
- case * PhysicalIndexMergeJoin :
1952
- if inlmjLeftOuter {
1953
- forcedLeftOuterJoins = append (forcedLeftOuterJoins , j )
1954
- }
1964
+ if p .satisfyIndexJoinHint (j ) {
1965
+ forcedLeftOuterJoins = append (forcedLeftOuterJoins , j )
1955
1966
}
1956
1967
}
1957
1968
switch {
@@ -1961,23 +1972,13 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ
1961
1972
return forcedLeftOuterJoins , true
1962
1973
}
1963
1974
}
1975
+
1964
1976
if supportRightOuter {
1965
1977
allRightOuterJoins = p .getIndexJoinByOuterIdx (prop , 1 )
1966
1978
forcedRightOuterJoins = make ([]PhysicalPlan , 0 , len (allRightOuterJoins ))
1967
1979
for _ , j := range allRightOuterJoins {
1968
- switch j .(type ) {
1969
- case * PhysicalIndexJoin :
1970
- if inljRightOuter {
1971
- forcedRightOuterJoins = append (forcedRightOuterJoins , j )
1972
- }
1973
- case * PhysicalIndexHashJoin :
1974
- if inlhjRightOuter {
1975
- forcedRightOuterJoins = append (forcedRightOuterJoins , j )
1976
- }
1977
- case * PhysicalIndexMergeJoin :
1978
- if inlmjRightOuter {
1979
- forcedRightOuterJoins = append (forcedRightOuterJoins , j )
1980
- }
1980
+ if p .satisfyIndexJoinHint (j ) {
1981
+ forcedRightOuterJoins = append (forcedRightOuterJoins , j )
1981
1982
}
1982
1983
}
1983
1984
switch {
0 commit comments