Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner: support limit_to_cop, agg_to_cop, ordered_index, no_ordered_index for quick binding #44611

Merged
merged 24 commits into from Jun 13, 2023
2 changes: 1 addition & 1 deletion executor/adapter.go
Expand Up @@ -1757,7 +1757,7 @@ func getEncodedPlan(stmtCtx *stmtctx.StatementContext, genHint bool) (encodedPla
switch tableHint.HintName.L {
case "memory_quota", "use_toja", "no_index_merge", "max_execution_time",
plannercore.HintAggToCop, plannercore.HintIgnoreIndex,
plannercore.HintReadFromStorage, plannercore.HintLimitToCop:
plannercore.HintReadFromStorage:
hints = append(hints, tableHint)
}
}
Expand Down
6 changes: 6 additions & 0 deletions infoschema/test/clustertablestest/cluster_tables_test.go
Expand Up @@ -931,6 +931,12 @@ func TestQuickBinding(t *testing.T) {
// 2-way merge joins
{`select /*+ merge_join(t1, t2), use_index(t1), use_index(t2) */ t1.* from t1, t2 where t1.a=t2.a and t1.a<?`, "merge_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` ), use_index(@`sel_1` `test`.`t2` )", nil},
{`select /*+ merge_join(t1, t2), use_index(t1, k_a), use_index(t2, k_a) */ t1.* from t1, t2 where t1.a=t2.a and t1.a<?`, "merge_join(@`sel_1` `test`.`t1`), use_index(@`sel_1` `test`.`t1` `k_a`), use_index(@`sel_1` `test`.`t2` `k_a`)", nil},

// limit_to_cop
{`select /*+ limit_to_cop(), use_index(t1, k_a) */ * from t1 where a < ? limit 100`, "use_index(@`sel_1` `test`.`t1` `k_a`), limit_to_cop(@`sel_1`)", nil},
{`select /*+ limit_to_cop(), use_index(t1, k_a) */ * from t1 where b < ? limit 100`, "use_index(@`sel_1` `test`.`t1` `k_a`), limit_to_cop(@`sel_1`)", nil},
{`select /*+ limit_to_cop(), use_index(t1, k_a) */ * from t1 where a < ? order by a limit 100`, "use_index(@`sel_1` `test`.`t1` `k_a`), limit_to_cop(@`sel_1`)", nil},
{`select /*+ limit_to_cop(), use_index(t1, k_a) */ * from t1 where a < ? order by b limit 100`, "use_index(@`sel_1` `test`.`t1` `k_a`), limit_to_cop(@`sel_1`)", nil},
}

removeHint := func(sql string) string {
Expand Down
18 changes: 11 additions & 7 deletions planner/core/hints.go
Expand Up @@ -40,19 +40,16 @@ func GenHintsFromFlatPlan(flat *FlatPhysicalPlan) []*ast.TableOptimizerHint {
return nil
}
for _, op := range selectPlan {
if !op.IsRoot {
continue
}
p := op.Origin.(PhysicalPlan)
hints = genHintsFromSingle(p, nodeTp, hints)
hints = genHintsFromSingle(p, nodeTp, op.StoreType, hints)
}
for _, cte := range flat.CTEs {
for i, op := range cte {
if i == 0 || !op.IsRoot {
continue
}
p := op.Origin.(PhysicalPlan)
hints = genHintsFromSingle(p, nodeTp, hints)
hints = genHintsFromSingle(p, nodeTp, op.StoreType, hints)
}
}
return hints
Expand Down Expand Up @@ -164,15 +161,22 @@ func genHintsFromPhysicalPlan(p PhysicalPlan, nodeType utilhint.NodeType) (res [
res = append(res, genHintsFromPhysicalPlan(phCte.CTE.recursivePartPhysicalPlan, nodeType)...)
}

return genHintsFromSingle(p, nodeType, res)
return genHintsFromSingle(p, nodeType, kv.TiDB, res)
}

func genHintsFromSingle(p PhysicalPlan, nodeType utilhint.NodeType, res []*ast.TableOptimizerHint) []*ast.TableOptimizerHint {
func genHintsFromSingle(p PhysicalPlan, nodeType utilhint.NodeType, storeType kv.StoreType, res []*ast.TableOptimizerHint) []*ast.TableOptimizerHint {
qbName, err := utilhint.GenerateQBName(nodeType, p.SelectBlockOffset())
if err != nil {
return res
}
switch pp := p.(type) {
case *PhysicalLimit, *PhysicalTopN:
if storeType == kv.TiKV {
res = append(res, &ast.TableOptimizerHint{
QBName: qbName,
HintName: model.NewCIStr(HintLimitToCop),
})
}
case *PhysicalTableReader:
tbl, ok := pp.TablePlans[0].(*PhysicalTableScan)
if !ok {
Expand Down