Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pkg/planner/core/joinorder/join_order.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,9 @@ func optimizeRecursive(p base.LogicalPlan) (base.LogicalPlan, error) {
}
if len(vertexMap) > 0 {
joinGroup.root = replaceJoinGroupVertexes(joinGroup.root, vertexMap)
if len(joinGroup.vertexHints) > 0 {
joinGroup.vertexHints = RebindJoinMethodHints(joinGroup.vertexHints, vertexMap)
}
}
if p, err = optimizeForJoinGroup(p.SCtx(), joinGroup); err != nil {
return nil, err
Expand Down
31 changes: 31 additions & 0 deletions pkg/planner/core/joinorder/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,37 @@ type JoinMethodHint struct {
HintInfo *hint.PlanHints
}

const indexJoinHintMask = hint.PreferINLJ | hint.PreferINLHJ | hint.PreferINLMJ |
hint.PreferNoIndexJoin | hint.PreferNoIndexHashJoin | hint.PreferNoIndexMergeJoin

// ShouldRebindJoinMethodHint reports whether a join method hint should follow
// the optimized vertex ID after recursive subtree optimization.
func ShouldRebindJoinMethodHint(preferJoinMethod uint) bool {
return preferJoinMethod&indexJoinHintMask != 0
}

// RebindJoinMethodHints remaps hint keys from pre-optimization plan IDs to the
// optimized vertex IDs after recursive subtree optimization rebuilds the child
// plans participating in join reorder.
func RebindJoinMethodHints(hints map[int]*JoinMethodHint, vertexMap map[int]base.LogicalPlan) map[int]*JoinMethodHint {
if len(hints) == 0 || len(vertexMap) == 0 {
return hints
}
rebuilt := make(map[int]*JoinMethodHint, len(hints))
for oldID, hintInfo := range hints {
if ShouldRebindJoinMethodHint(hintInfo.PreferJoinMethod) {
optimizedVertex, ok := vertexMap[oldID]
intest.Assert(ok, "join method hint vertex must be present in optimized vertex map")
if ok {
rebuilt[optimizedVertex.ID()] = hintInfo
continue
}
}
rebuilt[oldID] = hintInfo
}
return rebuilt
}

// CheckAndGenerateLeadingHint used to check and generate the valid leading hint.
// We are allowed to use at most one leading hint in a join group. When more than one,
// all leading hints in the current join group will be invalid.
Expand Down
57 changes: 57 additions & 0 deletions pkg/planner/core/physical_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,63 @@ func TestJoinHintCompatibilityWithVariable(t *testing.T) {
tk.MustExec("select /*+ leading(t2), hash_join(t2) */ * from t t1 join t t2 join t t3 where t1.a = t2.a and t2.b = t3.b;")
res := tk.MustQuery("show warnings").Rows()
require.Equal(t, len(res) > 0, true)
tk.MustExec("drop table if exists table_insurant, table_house, table_role_connection")
tk.MustExec("create table table_insurant(actualid varchar(32), serialNo varchar(32), key idx_actualid(actualid))")
tk.MustExec("create table table_house(actualid varchar(32), planNo varchar(32), topId varchar(32), insurantNo varchar(32), key idx_actualid(actualid), key idx_insurantNo(insurantNo))")
tk.MustExec("create table table_role_connection(actualid varchar(32), parentId varchar(32), specid varchar(32), key idx_parent_spec_actual(parentId, specid, actualid), key idx_actualid(actualid))")

tk.MustExec(`insert into table_insurant values
('a1', '2'),
('a2', '3')`)
tk.MustExec(`insert into table_house values
('h1', 'p1', 't1', '2'),
('h2', 'p2', 't2', '9')`)
tk.MustExec(`insert into table_role_connection values
('a1', '3561703379345', '14535'),
('h1', '3561703379345', '14550')`)

sql := `explain select
count(*)
from
(
select /*+ inl_join(t1) */
t2.actualId,
t2.planNo,
t2.topId,
t2.insurantNo
from
(
select *
from table_insurant
where actualid in (
select actualid
from table_role_connection
where parentId = '3561703379345'
and specid = '14535'
)
) t1,
(
select *
from table_house
where actualid in (
select actualid
from table_role_connection
where parentId = '3561703379345'
and specid = '14550'
)
) t2
where t1.serialNo = t2.insurantNo
and t2.insurantNo = '2'
) s`
expectedWarn := "Warning 1815 Optimizer Hint /*+ INL_JOIN(t1) */ or /*+ TIDB_INLJ(t1) */ is inapplicable"

tk.MustExec("set @@session.tidb_opt_advanced_join_hint=0")
tk.MustQuery(sql).Rows()
tk.MustQuery("show warnings").Check(testkit.Rows(expectedWarn))

tk.MustExec("set @@session.tidb_opt_advanced_join_hint=1")
tk.MustQuery(sql).Rows()
tk.MustQuery("show warnings").Check(testkit.Rows(expectedWarn))
Comment thread
hawkingrei marked this conversation as resolved.
})
}

Expand Down
6 changes: 6 additions & 0 deletions pkg/planner/core/rule_join_reorder.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,11 +312,17 @@ func (s *JoinReOrderSolver) optimizeRecursive(ctx base.PlanContext, p base.Logic
result := extractJoinGroup(p)
curJoinGroup, joinTypes, joinOrderHintInfo, hasOuterJoin := result.group, result.joinTypes, result.joinOrderHintInfo, result.hasOuterJoin
if len(curJoinGroup) > 1 {
optimizedVertexMap := make(map[int]base.LogicalPlan, len(curJoinGroup))
for i := range curJoinGroup {
oldID := curJoinGroup[i].ID()
curJoinGroup[i], err = s.optimizeRecursive(ctx, curJoinGroup[i])
if err != nil {
return nil, err
}
optimizedVertexMap[oldID] = curJoinGroup[i]
}
if len(result.joinMethodHintInfo) > 0 {
result.joinMethodHintInfo = joinorder.RebindJoinMethodHints(result.joinMethodHintInfo, optimizedVertexMap)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
originalSchema := p.Schema()

Expand Down
Loading