From 19d9dfdf68bcee535c9b2d0dc39ebe926811257f Mon Sep 17 00:00:00 2001 From: gauss Date: Fri, 13 Mar 2020 10:43:04 +0800 Subject: [PATCH 1/4] planner: support hint USE_CASCADES(true|false) to use/disuse cascades planner in a single query Signed-off-by: gauss --- planner/optimize.go | 18 +++++++++++++++--- session/session_test.go | 11 +++++++++++ sessionctx/stmtctx/stmtctx.go | 3 +++ sessionctx/variable/session.go | 15 ++++++++++++++- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/planner/optimize.go b/planner/optimize.go index 1aac017bb5d64..8e1530c2d5384 100644 --- a/planner/optimize.go +++ b/planner/optimize.go @@ -165,7 +165,7 @@ func optimize(ctx context.Context, sctx sessionctx.Context, node ast.Node, is in } // Handle the logical plan statement, use cascades planner if enabled. - if sctx.GetSessionVars().EnableCascadesPlanner { + if sctx.GetSessionVars().GetEnableCascadesPlanner() { finalPlan, cost, err := cascades.DefaultOptimizer.FindBestPlan(sctx, logic) return finalPlan, names, cost, err } @@ -297,8 +297,8 @@ func handleStmtHints(hints []*ast.TableOptimizerHint) (stmtHints stmtctx.StmtHin if len(hints) == 0 { return } - var memoryQuotaHint, useToJAHint, maxExecutionTime *ast.TableOptimizerHint - var memoryQuotaHintCnt, useToJAHintCnt, noIndexMergeHintCnt, readReplicaHintCnt, maxExecutionTimeCnt int + var memoryQuotaHint, useToJAHint, useCascadesHint, maxExecutionTime *ast.TableOptimizerHint + var memoryQuotaHintCnt, useToJAHintCnt, useCascadesHintCnt, noIndexMergeHintCnt, readReplicaHintCnt, maxExecutionTimeCnt int for _, hint := range hints { switch hint.HintName.L { case "memory_quota": @@ -307,6 +307,9 @@ func handleStmtHints(hints []*ast.TableOptimizerHint) (stmtHints stmtctx.StmtHin case "use_toja": useToJAHint = hint useToJAHintCnt++ + case "use_cascades": + useCascadesHint = hint + useCascadesHintCnt++ case "no_index_merge": noIndexMergeHintCnt++ case "read_consistent_replica": @@ -344,6 +347,15 @@ func handleStmtHints(hints []*ast.TableOptimizerHint) (stmtHints stmtctx.StmtHin stmtHints.HasAllowInSubqToJoinAndAggHint = true stmtHints.AllowInSubqToJoinAndAgg = useToJAHint.HintData.(bool) } + // Handle USE_CASCADES + if useCascadesHintCnt != 0 { + if useCascadesHintCnt > 1 { + warn := errors.New("There are multiple USE_CASCADES hints, only the last one will take effect") + warns = append(warns, warn) + } + stmtHints.HasEnableCascadesPlannerHint = true + stmtHints.EnableCascadesPlanner = useCascadesHint.HintData.(bool) + } // Handle NO_INDEX_MERGE if noIndexMergeHintCnt != 0 { if noIndexMergeHintCnt > 1 { diff --git a/session/session_test.go b/session/session_test.go index 6d87d072491f5..6718f8ff2c382 100644 --- a/session/session_test.go +++ b/session/session_test.go @@ -3048,6 +3048,17 @@ func (s *testSessionSuite2) TestStmtHints(c *C) { c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) c.Assert(tk.Se.GetSessionVars().GetAllowInSubqToJoinAndAgg(), IsTrue) + // Test USE_CASCADES hint + tk.Se.GetSessionVars().SetEnableCascadesPlanner(true) + tk.MustExec("select /*+ USE_CASCADES(false) */ 1;") + c.Assert(tk.Se.GetSessionVars().GetEnableCascadesPlanner(), IsFalse) + tk.Se.GetSessionVars().SetEnableCascadesPlanner(false) + tk.MustExec("select /*+ USE_CASCADES(true) */ 1;") + c.Assert(tk.Se.GetSessionVars().GetEnableCascadesPlanner(), IsTrue) + tk.MustExec("select /*+ USE_CASCADES(false), USE_CASCADES(true) */ 1;") + c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) + c.Assert(tk.Se.GetSessionVars().GetEnableCascadesPlanner(), IsTrue) + // Test READ_CONSISTENT_REPLICA hint tk.Se.GetSessionVars().SetReplicaRead(kv.ReplicaReadLeader) tk.MustExec("select /*+ READ_CONSISTENT_REPLICA() */ 1;") diff --git a/sessionctx/stmtctx/stmtctx.go b/sessionctx/stmtctx/stmtctx.go index 064a4ba40bd5a..96cf03140e9ba 100644 --- a/sessionctx/stmtctx/stmtctx.go +++ b/sessionctx/stmtctx/stmtctx.go @@ -153,12 +153,15 @@ type StmtHints struct { ReplicaRead byte AllowInSubqToJoinAndAgg bool NoIndexMergeHint bool + // EnableCascadesPlanner is use cascades planner for a single query only. + EnableCascadesPlanner bool // Hint flags HasAllowInSubqToJoinAndAggHint bool HasMemQuotaHint bool HasReplicaReadHint bool HasMaxExecutionTime bool + HasEnableCascadesPlannerHint bool } // GetNowTsCached getter for nowTs, if not set get now time and cache it diff --git a/sessionctx/variable/session.go b/sessionctx/variable/session.go index 61ff0603bedca..15694d69faffd 100644 --- a/sessionctx/variable/session.go +++ b/sessionctx/variable/session.go @@ -740,6 +740,19 @@ func (s *SessionVars) SetAllowInSubqToJoinAndAgg(val bool) { s.allowInSubqToJoinAndAgg = val } +// GetEnableCascadesPlanner get EnableCascadesPlanner from sql hints and SessionVars.EnableCascadesPlanner. +func (s *SessionVars) GetEnableCascadesPlanner() bool { + if s.StmtCtx.HasEnableCascadesPlannerHint { + return s.StmtCtx.EnableCascadesPlanner + } + return s.EnableCascadesPlanner +} + +// SetEnableCascadesPlanner set SessionVars.EnableCascadesPlanner. +func (s *SessionVars) SetEnableCascadesPlanner(val bool) { + s.EnableCascadesPlanner = val +} + // GetEnableIndexMerge get EnableIndexMerge from SessionVars.enableIndexMerge. func (s *SessionVars) GetEnableIndexMerge() bool { return s.enableIndexMerge @@ -1123,7 +1136,7 @@ func (s *SessionVars) SetSystemVar(name string, val string) error { case TiDBEnableChunkRPC: s.EnableChunkRPC = TiDBOptOn(val) case TiDBEnableCascadesPlanner: - s.EnableCascadesPlanner = TiDBOptOn(val) + s.SetEnableCascadesPlanner(TiDBOptOn(val)) case TiDBOptimizerSelectivityLevel: s.OptimizerSelectivityLevel = tidbOptPositiveInt32(val, DefTiDBOptimizerSelectivityLevel) case TiDBEnableTablePartition: From 5334caf5c0df0e886d63db2105883700ed665af0 Mon Sep 17 00:00:00 2001 From: gauss1314 Date: Sun, 15 Mar 2020 23:30:49 +0800 Subject: [PATCH 2/4] Update planner/optimize.go Co-Authored-By: Zhang Jian --- planner/optimize.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/optimize.go b/planner/optimize.go index 8e1530c2d5384..9bd8fdc06ae8e 100644 --- a/planner/optimize.go +++ b/planner/optimize.go @@ -350,7 +350,7 @@ func handleStmtHints(hints []*ast.TableOptimizerHint) (stmtHints stmtctx.StmtHin // Handle USE_CASCADES if useCascadesHintCnt != 0 { if useCascadesHintCnt > 1 { - warn := errors.New("There are multiple USE_CASCADES hints, only the last one will take effect") + warn := errors.Errorf("USE_CASCADES() is defined more than once, only the last definition takes effect: USE_CASCADES(%v)", useCascadesHint.HintData.(bool)) warns = append(warns, warn) } stmtHints.HasEnableCascadesPlannerHint = true From 257524cafe02b592fad9f4035b24d4715b31febc Mon Sep 17 00:00:00 2001 From: gauss Date: Sun, 15 Mar 2020 23:55:21 +0800 Subject: [PATCH 3/4] update parser --- go.mod | 4 ++-- go.sum | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 3b4a75d6b0871..a0b53a4bd5e90 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989 github.com/pingcap/kvproto v0.0.0-20200228095611-2cf9a243b8d5 github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd - github.com/pingcap/parser v0.0.0-20200305120128-bde9faa0df84 + github.com/pingcap/parser v0.0.0-20200315112143-3dc646cd6b52 github.com/pingcap/pd/v4 v4.0.0-beta.1.0.20200305072537-61d9f9cc35d3 github.com/pingcap/sysutil v0.0.0-20200309085538-962fd285f3bb github.com/pingcap/tidb-tools v4.0.0-beta.1.0.20200306084441-875bd09aa3d5+incompatible @@ -66,7 +66,7 @@ require ( golang.org/x/sys v0.0.0-20200113162924-86b910548bc1 golang.org/x/text v0.3.2 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect - golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb + golang.org/x/tools v0.0.0-20200313205530-4303120df7d8 google.golang.org/grpc v1.25.1 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 diff --git a/go.sum b/go.sum index ce1488dfee690..88c8c1b332913 100644 --- a/go.sum +++ b/go.sum @@ -269,6 +269,8 @@ github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd h1:CV3VsP3Z02MVtdpTMfE github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8= github.com/pingcap/parser v0.0.0-20200305120128-bde9faa0df84 h1:u5FOwUw9muF8mBTZVV1dQhoAKiEo2Ci54CxN9XchEEY= github.com/pingcap/parser v0.0.0-20200305120128-bde9faa0df84/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4= +github.com/pingcap/parser v0.0.0-20200315112143-3dc646cd6b52 h1:L8N5zWQOrQyDdpX8n/xYkIe/U8IuL/HYCVK9maD1EsQ= +github.com/pingcap/parser v0.0.0-20200315112143-3dc646cd6b52/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4= github.com/pingcap/pd/v4 v4.0.0-beta.1.0.20200305072537-61d9f9cc35d3 h1:Yrp99FnjHAEuDrSBql2l0IqCtJX7KwJbTsD5hIArkvk= github.com/pingcap/pd/v4 v4.0.0-beta.1.0.20200305072537-61d9f9cc35d3/go.mod h1:25GfNw6+Jcr9kca5rtmTb4gKCJ4jOpow2zV2S9Dgafs= github.com/pingcap/sysutil v0.0.0-20200206130906-2bfa6dc40bcd/go.mod h1:EB/852NMQ+aRKioCpToQ94Wl7fktV+FNnxf3CX/TTXI= @@ -370,6 +372,7 @@ github.com/urfave/negroni v0.3.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKn github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yookoala/realpath v1.0.0/go.mod h1:gJJMA9wuX7AcqLy1+ffPatSCySA1FQ2S8Ya9AIoYBpE= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= @@ -489,6 +492,8 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200301222351-066e0c02454c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb h1:iKlO7ROJc6SttHKlxzwGytRtBUqX4VARrNTgP2YLX5M= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200313205530-4303120df7d8 h1:gkI/wGGwpcG5W4hLCzZNGxA4wzWBGGDStRI1MrjDl2Q= +golang.org/x/tools v0.0.0-20200313205530-4303120df7d8/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From cf615a075b0e0e62a44870491ba13beef91278dc Mon Sep 17 00:00:00 2001 From: gauss Date: Mon, 16 Mar 2020 10:26:11 +0800 Subject: [PATCH 4/4] fix test case --- session/session_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/session/session_test.go b/session/session_test.go index 65ac26730ccde..8953e947ccc58 100644 --- a/session/session_test.go +++ b/session/session_test.go @@ -3057,6 +3057,7 @@ func (s *testSessionSuite2) TestStmtHints(c *C) { c.Assert(tk.Se.GetSessionVars().GetEnableCascadesPlanner(), IsTrue) tk.MustExec("select /*+ USE_CASCADES(false), USE_CASCADES(true) */ 1;") c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1) + c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings()[0].Err.Error(), Equals, "USE_CASCADES() is defined more than once, only the last definition takes effect: USE_CASCADES(true)") c.Assert(tk.Se.GetSessionVars().GetEnableCascadesPlanner(), IsTrue) // Test READ_CONSISTENT_REPLICA hint