planner: retrieve optimizer hint scope change (#12382)
This commit is contained in:
committed by
pingcap-github-bot
parent
7d54d8cd04
commit
fc577e705d
@ -1968,7 +1968,7 @@ func (b *PlanBuilder) unfoldWildStar(p LogicalPlan, selectFields []*ast.SelectFi
|
||||
return resultList, nil
|
||||
}
|
||||
|
||||
func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, nodeType nodeType, currentLevel int) bool {
|
||||
func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, nodeType nodeType, currentLevel int) {
|
||||
hints = b.hintProcessor.getCurrentStmtHints(hints, nodeType, currentLevel)
|
||||
var (
|
||||
sortMergeTables, INLJTables, hashJoinTables []hintTableInfo
|
||||
@ -2015,17 +2015,13 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, nodeType n
|
||||
// ignore hints that not implemented
|
||||
}
|
||||
}
|
||||
if len(sortMergeTables)+len(INLJTables)+len(hashJoinTables)+len(indexHintList) > 0 || aggHints.preferAggType != 0 || aggHints.preferAggToCop {
|
||||
b.tableHintInfo = append(b.tableHintInfo, tableHintInfo{
|
||||
sortMergeJoinTables: sortMergeTables,
|
||||
indexNestedLoopJoinTables: INLJTables,
|
||||
hashJoinTables: hashJoinTables,
|
||||
indexHintList: indexHintList,
|
||||
aggHints: aggHints,
|
||||
})
|
||||
return true
|
||||
}
|
||||
return false
|
||||
b.tableHintInfo = append(b.tableHintInfo, tableHintInfo{
|
||||
sortMergeJoinTables: sortMergeTables,
|
||||
indexNestedLoopJoinTables: INLJTables,
|
||||
hashJoinTables: hashJoinTables,
|
||||
indexHintList: indexHintList,
|
||||
aggHints: aggHints,
|
||||
})
|
||||
}
|
||||
|
||||
func (b *PlanBuilder) popTableHints() {
|
||||
@ -2056,11 +2052,12 @@ func (b *PlanBuilder) TableHints() *tableHintInfo {
|
||||
|
||||
func (b *PlanBuilder) buildSelect(ctx context.Context, sel *ast.SelectStmt) (p LogicalPlan, err error) {
|
||||
b.pushSelectOffset(sel.QueryBlockOffset)
|
||||
defer b.popSelectOffset()
|
||||
if b.pushTableHints(sel.TableHints, typeSelect, sel.QueryBlockOffset) {
|
||||
b.pushTableHints(sel.TableHints, typeSelect, sel.QueryBlockOffset)
|
||||
defer func() {
|
||||
b.popSelectOffset()
|
||||
// table hints are only visible in the current SELECT statement.
|
||||
defer b.popTableHints()
|
||||
}
|
||||
b.popTableHints()
|
||||
}()
|
||||
|
||||
if sel.SelectStmtOpts != nil {
|
||||
origin := b.inStraightJoin
|
||||
@ -2708,11 +2705,12 @@ func buildColumns2Handle(
|
||||
|
||||
func (b *PlanBuilder) buildUpdate(ctx context.Context, update *ast.UpdateStmt) (Plan, error) {
|
||||
b.pushSelectOffset(0)
|
||||
defer b.popSelectOffset()
|
||||
if b.pushTableHints(update.TableHints, typeUpdate, 0) {
|
||||
b.pushTableHints(update.TableHints, typeUpdate, 0)
|
||||
defer func() {
|
||||
b.popSelectOffset()
|
||||
// table hints are only visible in the current UPDATE statement.
|
||||
defer b.popTableHints()
|
||||
}
|
||||
b.popTableHints()
|
||||
}()
|
||||
|
||||
// update subquery table should be forbidden
|
||||
var asNameList []string
|
||||
@ -2959,11 +2957,12 @@ func extractTableAsNameForUpdate(p LogicalPlan, asNames map[*model.TableInfo][]*
|
||||
|
||||
func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) (Plan, error) {
|
||||
b.pushSelectOffset(0)
|
||||
defer b.popSelectOffset()
|
||||
if b.pushTableHints(delete.TableHints, typeDelete, 0) {
|
||||
b.pushTableHints(delete.TableHints, typeDelete, 0)
|
||||
defer func() {
|
||||
b.popSelectOffset()
|
||||
// table hints are only visible in the current DELETE statement.
|
||||
defer b.popTableHints()
|
||||
}
|
||||
b.popTableHints()
|
||||
}()
|
||||
|
||||
p, err := b.buildResultSetNode(ctx, delete.TableRefs.TableRefs)
|
||||
if err != nil {
|
||||
|
||||
@ -660,6 +660,43 @@ func (s *testPlanSuite) TestUnmatchedTableInHint(c *C) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *testPlanSuite) TestHintScope(c *C) {
|
||||
defer testleak.AfterTest(c)()
|
||||
store, dom, err := newStoreWithBootstrap()
|
||||
c.Assert(err, IsNil)
|
||||
defer func() {
|
||||
dom.Close()
|
||||
store.Close()
|
||||
}()
|
||||
se, err := session.CreateSession4Test(store)
|
||||
c.Assert(err, IsNil)
|
||||
_, err = se.Execute(context.Background(), "use test")
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
var input []string
|
||||
var output []struct {
|
||||
SQL string
|
||||
Best string
|
||||
}
|
||||
s.testData.GetTestCases(c, &input, &output)
|
||||
for i, test := range input {
|
||||
comment := Commentf("case:%v sql:%s", i, test)
|
||||
stmt, err := s.ParseOneStmt(test, "", "")
|
||||
c.Assert(err, IsNil, comment)
|
||||
|
||||
p, err := planner.Optimize(context.Background(), se, stmt, s.is)
|
||||
c.Assert(err, IsNil)
|
||||
s.testData.OnRecord(func() {
|
||||
output[i].SQL = test
|
||||
output[i].Best = core.ToString(p)
|
||||
})
|
||||
c.Assert(core.ToString(p), Equals, output[i].Best)
|
||||
|
||||
warnings := se.GetSessionVars().StmtCtx.GetWarnings()
|
||||
c.Assert(warnings, HasLen, 0, comment)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *testPlanSuite) TestJoinHints(c *C) {
|
||||
defer testleak.AfterTest(c)()
|
||||
store, dom, err := newStoreWithBootstrap()
|
||||
|
||||
20
planner/core/testdata/plan_suite_in.json
vendored
20
planner/core/testdata/plan_suite_in.json
vendored
@ -1,4 +1,24 @@
|
||||
[
|
||||
{
|
||||
"name": "TestHintScope",
|
||||
"cases": [
|
||||
// join hints
|
||||
"select /*+ SM_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ INL_JOIN(t3) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"select /*+ SM_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ HASH_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ HASH_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ SM_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ SM_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ INL_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"select /*+ SM_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
// aggregation hints
|
||||
"select /*+ STREAM_AGG() */ s, count(s) from (select /*+ HASH_AGG() */ sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s",
|
||||
"select /*+ HASH_AGG() */ s, count(s) from (select /*+ STREAM_AGG() */ sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s",
|
||||
"select /*+ HASH_AGG() */ s, count(s) from (select sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s",
|
||||
"select /*+ STREAM_AGG() */ s, count(s) from (select sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TestIndexHint",
|
||||
"cases": [
|
||||
|
||||
57
planner/core/testdata/plan_suite_out.json
vendored
57
planner/core/testdata/plan_suite_out.json
vendored
@ -1,4 +1,61 @@
|
||||
[
|
||||
{
|
||||
"Name": "TestHintScope",
|
||||
"Cases": [
|
||||
{
|
||||
"SQL": "select /*+ SM_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ INL_JOIN(t3) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"Best": "MergeInnerJoin{TableReader(Table(t))->IndexMergeJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(Column#13,Column#27)}(Column#1,Column#13)->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ SM_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ HASH_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"Best": "MergeInnerJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(Column#13,Column#27)->Sort}(Column#1,Column#13)->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ HASH_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"Best": "IndexMergeJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(Column#13,Column#27)}(Column#13,Column#1)->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ SM_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"Best": "IndexMergeJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(Column#13,Column#27)}(Column#13,Column#1)->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ SM_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"Best": "RightHashJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(Column#13,Column#27)}(Column#1,Column#13)->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select /*+ INL_JOIN(t2) */ t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"Best": "RightHashJoin{TableReader(Table(t))->IndexMergeJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(Column#27,Column#13)}(Column#1,Column#13)->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ SM_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"Best": "MergeInnerJoin{TableReader(Table(t))->MergeInnerJoin{TableReader(Table(t))->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(Column#13,Column#27)}(Column#1,Column#13)->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ INL_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"Best": "IndexMergeJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(Column#13,Column#27)}(Column#13,Column#1)->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ HASH_JOIN(t1) */ t1.a, t1.b from t t1, (select t2.a from t t2, t t3 where t2.a = t3.c) s where t1.a=s.a",
|
||||
"Best": "RightHashJoin{TableReader(Table(t))->LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->IndexReader(Index(t.c_d_e)[[NULL,+inf]])}(Column#13,Column#27)}(Column#1,Column#13)->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ STREAM_AGG() */ s, count(s) from (select /*+ HASH_AGG() */ sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s",
|
||||
"Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(Column#1,Column#14)->Projection->HashAgg->Sort->StreamAgg->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ HASH_AGG() */ s, count(s) from (select /*+ STREAM_AGG() */ sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s",
|
||||
"Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(Column#1,Column#14)->Sort->Projection->StreamAgg->HashAgg->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ HASH_AGG() */ s, count(s) from (select sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s",
|
||||
"Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(Column#1,Column#14)->Projection->HashAgg->HashAgg->Projection"
|
||||
},
|
||||
{
|
||||
"SQL": "select /*+ STREAM_AGG() */ s, count(s) from (select sum(t1.a) as s from t t1, t t2 where t1.a = t2.b group by t1.a) p group by s",
|
||||
"Best": "LeftHashJoin{IndexReader(Index(t.f)[[NULL,+inf]])->TableReader(Table(t))}(Column#1,Column#14)->Projection->HashAgg->Sort->StreamAgg->Projection"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "TestIndexHint",
|
||||
"Cases": [
|
||||
|
||||
Reference in New Issue
Block a user