Skip to content

Commit

Permalink
This is an automated cherry-pick of #45633
Browse files Browse the repository at this point in the history
Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io>
  • Loading branch information
qw4990 authored and ti-chi-bot committed Jul 28, 2023
1 parent e44839c commit 5d141c4
Show file tree
Hide file tree
Showing 8 changed files with 11,193 additions and 0 deletions.
35 changes: 35 additions & 0 deletions planner/core/casetest/rule/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
load("@io_bazel_rules_go//go:def.bzl", "go_test")

go_test(
name = "rule_test",
timeout = "short",
srcs = [
"main_test.go",
"rule_derive_topn_from_window_test.go",
"rule_inject_extra_projection_test.go",
"rule_join_reorder_test.go",
"rule_result_reorder_test.go",
],
data = glob(["testdata/**"]),
flaky = True,
shard_count = 23,
deps = [
"//domain",
"//expression",
"//expression/aggregation",
"//parser/ast",
"//parser/model",
"//parser/mysql",
"//planner/core/internal",
"//sessionctx/variable",
"//testkit",
"//testkit/testdata",
"//testkit/testmain",
"//testkit/testsetup",
"//types",
"//util/mock",
"@com_github_pingcap_failpoint//:failpoint",
"@com_github_stretchr_testify//require",
"@org_uber_go_goleak//:goleak",
],
)
339 changes: 339 additions & 0 deletions planner/core/casetest/rule/rule_join_reorder_test.go

Large diffs are not rendered by default.

518 changes: 518 additions & 0 deletions planner/core/casetest/rule/testdata/join_reorder_suite_in.json

Large diffs are not rendered by default.

10,168 changes: 10,168 additions & 0 deletions planner/core/casetest/rule/testdata/join_reorder_suite_out.json

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions planner/core/exhaust_physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -1953,6 +1953,7 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ
}
}
if supportRightOuter {
<<<<<<< HEAD
allRightOuterJoins = p.getIndexJoinByOuterIdx(prop, 1)
forcedRightOuterJoins = make([]PhysicalPlan, 0, len(allRightOuterJoins))
for _, j := range allRightOuterJoins {
Expand All @@ -1970,6 +1971,64 @@ func (p *LogicalJoin) tryToGetIndexJoin(prop *property.PhysicalProperty) (indexJ
forcedRightOuterJoins = append(forcedRightOuterJoins, j)
}
}
=======
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.
// Handle hints conflict first.
stmtCtx := p.SCtx().GetSessionVars().StmtCtx
if p.preferAny(preferLeftAsINLJInner, preferRightAsINLJInner) && p.preferAny(preferNoIndexJoin) {
stmtCtx.AppendWarning(ErrInternal.GenWithStack("Some INL_JOIN and NO_INDEX_JOIN hints conflict, NO_INDEX_JOIN may be ignored"))
}
if p.preferAny(preferLeftAsINLHJInner, preferRightAsINLHJInner) && p.preferAny(preferNoIndexHashJoin) {
stmtCtx.AppendWarning(ErrInternal.GenWithStack("Some INL_HASH_JOIN and NO_INDEX_HASH_JOIN hints conflict, NO_INDEX_HASH_JOIN may be ignored"))
}
if p.preferAny(preferLeftAsINLMJInner, preferRightAsINLMJInner) && p.preferAny(preferNoIndexMergeJoin) {
stmtCtx.AppendWarning(ErrInternal.GenWithStack("Some INL_MERGE_JOIN and NO_INDEX_MERGE_JOIN hints conflict, NO_INDEX_MERGE_JOIN may be ignored"))
}

candidates, canForced = p.handleForceIndexJoinHints(prop, candidates)
if canForced {
return candidates, canForced
}
candidates = p.handleFilterIndexJoinHints(candidates)
return filterIndexJoinBySessionVars(p.SCtx(), candidates), false
}

func (p *LogicalJoin) handleFilterIndexJoinHints(candidates []PhysicalPlan) []PhysicalPlan {
if !p.preferAny(preferNoIndexJoin, preferNoIndexHashJoin, preferNoIndexMergeJoin) {
return candidates // no filter index join hints
}
filtered := make([]PhysicalPlan, 0, len(candidates))
for _, candidate := range candidates {
_, joinMethod, ok := p.getIndexJoinSideAndMethod(candidate)
if !ok {
continue
}
if (p.preferAny(preferNoIndexJoin) && joinMethod == indexJoinMethod) ||
(p.preferAny(preferNoIndexHashJoin) && joinMethod == indexHashJoinMethod) ||
(p.preferAny(preferNoIndexMergeJoin) && joinMethod == indexMergeJoinMethod) {
continue
}
filtered = append(filtered, candidate)
}
return filtered
}

// 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) {
return candidates, false // no force index join hints
}
forced := make([]PhysicalPlan, 0, len(candidates))
for _, candidate := range candidates {
innerSide, joinMethod, ok := p.getIndexJoinSideAndMethod(candidate)
if !ok {
continue
>>>>>>> c266a9791c5 (planner: support `no_index_join`, `no_index_hash_join`, `no_index_merge_join` hints (#45633))
}
switch {
case len(forcedRightOuterJoins) == 0 && !supportLeftOuter:
Expand Down
54 changes: 54 additions & 0 deletions planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ const (
HintINLHJ = "inl_hash_join"
// HintINLMJ is hint enforce index nested loop merge join.
HintINLMJ = "inl_merge_join"
// HintNoIndexJoin is the hint to enforce the query not to use index join.
HintNoIndexJoin = "no_index_join"
// HintNoIndexHashJoin is the hint to enforce the query not to use index hash join.
HintNoIndexHashJoin = "no_index_hash_join"
// HintNoIndexMergeJoin is the hint to enforce the query not to use index merge join.
HintNoIndexMergeJoin = "no_index_merge_join"
// TiDBHashJoin is hint enforce hash join.
TiDBHashJoin = "tidb_hj"
// HintNoHashJoin is the hint to enforce the query not to use hash join.
Expand Down Expand Up @@ -657,6 +663,30 @@ func (p *LogicalJoin) setPreferredJoinTypeAndOrder(hintInfo *tableHintInfo) {
p.preferJoinType |= preferRightAsINLMJInner
p.rightPreferJoinType |= preferINLMJ
}
if hintInfo.ifPreferNoIndexJoin(lhsAlias) {
p.preferJoinType |= preferNoIndexJoin
p.leftPreferJoinType |= preferNoIndexJoin
}
if hintInfo.ifPreferNoIndexJoin(rhsAlias) {
p.preferJoinType |= preferNoIndexJoin
p.rightPreferJoinType |= preferNoIndexJoin
}
if hintInfo.ifPreferNoIndexHashJoin(lhsAlias) {
p.preferJoinType |= preferNoIndexHashJoin
p.leftPreferJoinType |= preferNoIndexHashJoin
}
if hintInfo.ifPreferNoIndexHashJoin(rhsAlias) {
p.preferJoinType |= preferNoIndexHashJoin
p.rightPreferJoinType |= preferNoIndexHashJoin
}
if hintInfo.ifPreferNoIndexMergeJoin(lhsAlias) {
p.preferJoinType |= preferNoIndexMergeJoin
p.leftPreferJoinType |= preferNoIndexMergeJoin
}
if hintInfo.ifPreferNoIndexMergeJoin(rhsAlias) {
p.preferJoinType |= preferNoIndexMergeJoin
p.rightPreferJoinType |= preferNoIndexMergeJoin
}
if hintInfo.ifPreferHJBuild(lhsAlias) {
p.preferJoinType |= preferLeftAsHJBuild
p.leftPreferJoinType |= preferHJBuild
Expand Down Expand Up @@ -3698,7 +3728,12 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev
hints = b.hintProcessor.GetCurrentStmtHints(hints, currentLevel)
var (
sortMergeTables, inljTables, inlhjTables, inlmjTables, hashJoinTables, bcTables []hintTableInfo
<<<<<<< HEAD
noHashJoinTables []hintTableInfo
=======
noIndexJoinTables, noIndexHashJoinTables, noIndexMergeJoinTables []hintTableInfo
noHashJoinTables, noMergeJoinTables []hintTableInfo
>>>>>>> c266a9791c5 (planner: support `no_index_join`, `no_index_hash_join`, `no_index_merge_join` hints (#45633))
shuffleJoinTables []hintTableInfo
indexHintList, indexMergeHintList []indexHintInfo
tiflashTables, tikvTables []hintTableInfo
Expand Down Expand Up @@ -3738,6 +3773,17 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev
hashJoinTables = append(hashJoinTables, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...)
case HintNoHashJoin:
noHashJoinTables = append(noHashJoinTables, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...)
<<<<<<< HEAD
=======
case HintNoMergeJoin:
noMergeJoinTables = append(noMergeJoinTables, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...)
case HintNoIndexJoin:
noIndexJoinTables = append(noIndexJoinTables, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...)
case HintNoIndexHashJoin:
noIndexHashJoinTables = append(noIndexHashJoinTables, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...)
case HintNoIndexMergeJoin:
noIndexMergeJoinTables = append(noIndexMergeJoinTables, tableNames2HintTableInfo(b.ctx, hint.HintName.L, hint.Tables, b.hintProcessor, currentLevel)...)
>>>>>>> c266a9791c5 (planner: support `no_index_join`, `no_index_hash_join`, `no_index_merge_join` hints (#45633))
case HintMPP1PhaseAgg:
aggHints.preferAggType |= preferMPP1PhaseAgg
case HintMPP2PhaseAgg:
Expand Down Expand Up @@ -3847,6 +3893,7 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev
broadcastJoinTables: bcTables,
shuffleJoinTables: shuffleJoinTables,
indexNestedLoopJoinTables: indexNestedLoopJoinTables{inljTables, inlhjTables, inlmjTables},
noIndexJoinTables: indexNestedLoopJoinTables{noIndexJoinTables, noIndexHashJoinTables, noIndexMergeJoinTables},
hashJoinTables: hashJoinTables,
noHashJoinTables: noHashJoinTables,
indexHintList: indexHintList,
Expand Down Expand Up @@ -7064,6 +7111,13 @@ func getInnerFromParenthesesAndUnaryPlus(expr ast.ExprNode) ast.ExprNode {
// join types.
func containDifferentJoinTypes(preferJoinType uint) bool {
preferJoinType &= ^preferNoHashJoin
<<<<<<< HEAD
=======
preferJoinType &= ^preferNoMergeJoin
preferJoinType &= ^preferNoIndexJoin
preferJoinType &= ^preferNoIndexHashJoin
preferJoinType &= ^preferNoIndexMergeJoin
>>>>>>> c266a9791c5 (planner: support `no_index_join`, `no_index_hash_join`, `no_index_merge_join` hints (#45633))

inlMask := preferRightAsINLJInner ^ preferLeftAsINLJInner
inlhjMask := preferRightAsINLHJInner ^ preferLeftAsINLHJInner
Expand Down
7 changes: 7 additions & 0 deletions planner/core/logical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ const (
preferHashJoin
preferNoHashJoin
preferMergeJoin
<<<<<<< HEAD
=======
preferNoMergeJoin
preferNoIndexJoin
preferNoIndexHashJoin
preferNoIndexMergeJoin
>>>>>>> c266a9791c5 (planner: support `no_index_join`, `no_index_hash_join`, `no_index_merge_join` hints (#45633))
preferBCJoin
preferShuffleJoin
preferRewriteSemiJoin
Expand Down
13 changes: 13 additions & 0 deletions planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ type indexNestedLoopJoinTables struct {

type tableHintInfo struct {
indexNestedLoopJoinTables
noIndexJoinTables indexNestedLoopJoinTables
sortMergeJoinTables []hintTableInfo
broadcastJoinTables []hintTableInfo
shuffleJoinTables []hintTableInfo
Expand Down Expand Up @@ -262,6 +263,18 @@ func (info *tableHintInfo) ifPreferINLMJ(tableNames ...*hintTableInfo) bool {
return info.matchTableName(tableNames, info.indexNestedLoopJoinTables.inlmjTables)
}

func (info *tableHintInfo) ifPreferNoIndexJoin(tableNames ...*hintTableInfo) bool {
return info.matchTableName(tableNames, info.noIndexJoinTables.inljTables)
}

func (info *tableHintInfo) ifPreferNoIndexHashJoin(tableNames ...*hintTableInfo) bool {
return info.matchTableName(tableNames, info.noIndexJoinTables.inlhjTables)
}

func (info *tableHintInfo) ifPreferNoIndexMergeJoin(tableNames ...*hintTableInfo) bool {
return info.matchTableName(tableNames, info.noIndexJoinTables.inlmjTables)
}

func (info *tableHintInfo) ifPreferTiFlash(tableName *hintTableInfo) *hintTableInfo {
if tableName == nil {
return nil
Expand Down

0 comments on commit 5d141c4

Please sign in to comment.