Skip to content

Commit

Permalink
planner: retrieve optimizer hint scope change (#12382)
Browse files Browse the repository at this point in the history
  • Loading branch information
foreyes authored and sre-bot committed Oct 8, 2019
1 parent 7d54d8c commit fc577e7
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 24 deletions.
47 changes: 23 additions & 24 deletions planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
37 changes: 37 additions & 0 deletions planner/core/physical_plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
20 changes: 20 additions & 0 deletions planner/core/testdata/plan_suite_in.json
Original file line number Diff line number Diff line change
@@ -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": [
Expand Down
57 changes: 57 additions & 0 deletions planner/core/testdata/plan_suite_out.json
Original file line number Diff line number Diff line change
@@ -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": [
Expand Down

0 comments on commit fc577e7

Please sign in to comment.