From 2e499f89317d276ca4cca1a6cc30640ca7f4e633 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Wed, 7 Dec 2022 20:09:18 +0800 Subject: [PATCH 01/16] commit --- infoschema/tables.go | 3 +++ infoschema/tables_test.go | 26 ++++++++++++++++++++++++++ util/stmtsummary/reader.go | 12 ++++++++++++ 3 files changed, 41 insertions(+) diff --git a/infoschema/tables.go b/infoschema/tables.go index d76d8b8be60b0..488c15ad09a70 100644 --- a/infoschema/tables.go +++ b/infoschema/tables.go @@ -1323,6 +1323,9 @@ var tableStatementsSummaryCols = []columnInfo{ {name: stmtsummary.PlanDigestStr, tp: mysql.TypeVarchar, size: 64, comment: "Digest of its execution plan"}, {name: stmtsummary.PlanStr, tp: mysql.TypeBlob, size: types.UnspecifiedLength, comment: "Sampled execution plan"}, {name: stmtsummary.BinaryPlan, tp: mysql.TypeBlob, size: types.UnspecifiedLength, comment: "Sampled binary plan"}, + {name: stmtsummary.Charset, tp: mysql.TypeVarchar, size: 64, comment: "Sampled charset"}, + {name: stmtsummary.Collation, tp: mysql.TypeVarchar, size: 64, comment: "Sampled charset"}, + {name: stmtsummary.PlanHint, tp: mysql.TypeVarchar, size: 64, comment: "Sampled charset"}, } var tableStorageStatsCols = []columnInfo{ diff --git a/infoschema/tables_test.go b/infoschema/tables_test.go index bd6168d035873..63cd85b071789 100644 --- a/infoschema/tables_test.go +++ b/infoschema/tables_test.go @@ -1661,3 +1661,29 @@ func TestMemoryUsageAndOpsHistory(t *testing.T) { require.Equal(t, row[10], "e3237ec256015a3566757e0c2742507cd30ae04e4cac2fbc14d269eafe7b067b") // SQL_DIGEST require.Equal(t, row[11], "explain analyze select * from t t1 join t t2 join t t3 on t1.a=t2.a and t1.a=t3.a order by t1.a") // SQL_TEXT } + +func TestAddFieldsForBinding(t *testing.T) { + s := new(clusterTablesSuite) + s.store, s.dom = testkit.CreateMockStoreAndDomain(t) + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil) + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + tk := s.newTestKitWithRoot(t) + + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int, key(a))") + tk.MustExec("select /*+ ignore_index(t, a)*/ * from t where a = 1") + planDigest := "4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb" + rows := tk.MustQuery(fmt.Sprintf("select schema_name, query_sample_text, charset, collation, plan_hint from information_schema.cluster_statements_summary where plan_digest = '%s'", planDigest)).Rows() + + require.Equal(t, rows[0][0], "test") + require.Equal(t, rows[0][1], "select /*+ ignore_index(t, a)*/ * from t where a = 1") + require.Equal(t, rows[0][2], "utf8mb4") + require.Equal(t, rows[0][3], "utf8mb4_bin") + require.Equal(t, rows[0][4], "use_index(@`sel_1` `test`.`t` ), ignore_index(`t` `a`)") + fmt.Println(planDigest) +} diff --git a/util/stmtsummary/reader.go b/util/stmtsummary/reader.go index eca48ae4e82eb..e5e9a2db39705 100644 --- a/util/stmtsummary/reader.go +++ b/util/stmtsummary/reader.go @@ -310,6 +310,9 @@ const ( PlanDigestStr = "PLAN_DIGEST" PlanStr = "PLAN" BinaryPlan = "BINARY_PLAN" + Charset = "CHARSET" + Collation = "COLLATION" + PlanHint = "PLAN_HINT" ) type columnValueFactory func(reader *stmtSummaryReader, ssElement *stmtSummaryByDigestElement, ssbd *stmtSummaryByDigest) interface{} @@ -620,4 +623,13 @@ var columnValueFactoryMap = map[string]columnValueFactory{ BinaryPlan: func(_ *stmtSummaryReader, ssElement *stmtSummaryByDigestElement, _ *stmtSummaryByDigest) interface{} { return ssElement.sampleBinaryPlan }, + Charset: func(_ *stmtSummaryReader, ssElement *stmtSummaryByDigestElement, _ *stmtSummaryByDigest) interface{} { + return ssElement.charset + }, + Collation: func(_ *stmtSummaryReader, ssElement *stmtSummaryByDigestElement, _ *stmtSummaryByDigest) interface{} { + return ssElement.collation + }, + PlanHint: func(_ *stmtSummaryReader, ssElement *stmtSummaryByDigestElement, _ *stmtSummaryByDigest) interface{} { + return ssElement.planHint + }, } From c1682ac59db74b005d8fcb672392c630e72e9800 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Thu, 8 Dec 2022 10:47:03 +0800 Subject: [PATCH 02/16] Update tables.go --- infoschema/tables.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infoschema/tables.go b/infoschema/tables.go index 488c15ad09a70..2f481d4e004b5 100644 --- a/infoschema/tables.go +++ b/infoschema/tables.go @@ -1324,8 +1324,8 @@ var tableStatementsSummaryCols = []columnInfo{ {name: stmtsummary.PlanStr, tp: mysql.TypeBlob, size: types.UnspecifiedLength, comment: "Sampled execution plan"}, {name: stmtsummary.BinaryPlan, tp: mysql.TypeBlob, size: types.UnspecifiedLength, comment: "Sampled binary plan"}, {name: stmtsummary.Charset, tp: mysql.TypeVarchar, size: 64, comment: "Sampled charset"}, - {name: stmtsummary.Collation, tp: mysql.TypeVarchar, size: 64, comment: "Sampled charset"}, - {name: stmtsummary.PlanHint, tp: mysql.TypeVarchar, size: 64, comment: "Sampled charset"}, + {name: stmtsummary.Collation, tp: mysql.TypeVarchar, size: 64, comment: "Sampled collation"}, + {name: stmtsummary.PlanHint, tp: mysql.TypeVarchar, size: 64, comment: "Sampled plan hint"}, } var tableStorageStatsCols = []columnInfo{ From c6c1fcecdbdeca48288e8f9726937872bfa9a8da Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Thu, 8 Dec 2022 12:04:51 +0800 Subject: [PATCH 03/16] Update index_merge.result --- cmd/explaintest/r/index_merge.result | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/explaintest/r/index_merge.result b/cmd/explaintest/r/index_merge.result index 0233dbdb55f52..6b44c6122987e 100644 --- a/cmd/explaintest/r/index_merge.result +++ b/cmd/explaintest/r/index_merge.result @@ -455,9 +455,9 @@ c1 c2 c3 ///// MEMORY Table explain select count(c1) from (select /*+ use_index_merge(t_alias), stream_agg() */ count(1) c1 from information_schema.statements_summary where sum_latency >= 0 or max_latency >= 0 order by 1) dt; id estRows task access object operator info -StreamAgg_10 1.00 root funcs:count(Column#93)->Column#94 -└─Sort_11 1.00 root Column#93 - └─StreamAgg_14 1.00 root funcs:count(1)->Column#93 +StreamAgg_10 1.00 root funcs:count(Column#96)->Column#97 +└─Sort_11 1.00 root Column#96 + └─StreamAgg_14 1.00 root funcs:count(1)->Column#96 └─MemTableScan_18 10000.00 root table:STATEMENTS_SUMMARY show warnings; Level Code Message From 39b6a2d1c22e9a5a2c407fbb7d59be2516927824 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Thu, 8 Dec 2022 12:39:10 +0800 Subject: [PATCH 04/16] ut --- infoschema/tables_test.go | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/infoschema/tables_test.go b/infoschema/tables_test.go index 63cd85b071789..23075793b1641 100644 --- a/infoschema/tables_test.go +++ b/infoschema/tables_test.go @@ -1678,12 +1678,16 @@ func TestAddFieldsForBinding(t *testing.T) { tk.MustExec("create table t(a int, key(a))") tk.MustExec("select /*+ ignore_index(t, a)*/ * from t where a = 1") planDigest := "4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb" - rows := tk.MustQuery(fmt.Sprintf("select schema_name, query_sample_text, charset, collation, plan_hint from information_schema.cluster_statements_summary where plan_digest = '%s'", planDigest)).Rows() - - require.Equal(t, rows[0][0], "test") - require.Equal(t, rows[0][1], "select /*+ ignore_index(t, a)*/ * from t where a = 1") - require.Equal(t, rows[0][2], "utf8mb4") - require.Equal(t, rows[0][3], "utf8mb4_bin") - require.Equal(t, rows[0][4], "use_index(@`sel_1` `test`.`t` ), ignore_index(`t` `a`)") + rows := tk.MustQuery(fmt.Sprintf("select stmt_type, prepared, sample_user, schema_name, query_sample_text, charset, collation, plan_hint "+ + "from information_schema.cluster_statements_summary where plan_digest = '%s'", planDigest)).Rows() + + require.Equal(t, rows[0][0], "Select") + require.Equal(t, rows[0][1], "0") + require.Equal(t, rows[0][2], "root") + require.Equal(t, rows[0][3], "test") + require.Equal(t, rows[0][4], "select /*+ ignore_index(t, a)*/ * from t where a = 1") + require.Equal(t, rows[0][5], "utf8mb4") + require.Equal(t, rows[0][6], "utf8mb4_bin") + require.Equal(t, rows[0][7], "use_index(@`sel_1` `test`.`t` ), ignore_index(`t` `a`)") fmt.Println(planDigest) } From c07c34cfda548b99745636cc1a87befa3a6d8170 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Thu, 8 Dec 2022 16:59:08 +0800 Subject: [PATCH 05/16] cluster --- bindinfo/bind_test.go | 105 ---------------------- infoschema/cluster_tables_test.go | 124 ++++++++++++++++++++++++++ planner/core/planbuilder.go | 28 +++++- util/stmtsummary/statement_summary.go | 47 ++++------ 4 files changed, 166 insertions(+), 138 deletions(-) diff --git a/bindinfo/bind_test.go b/bindinfo/bind_test.go index 052e5ecab2b18..cb8e62687df8f 100644 --- a/bindinfo/bind_test.go +++ b/bindinfo/bind_test.go @@ -1388,108 +1388,3 @@ func TestDropBindBySQLDigest(t *testing.T) { tk.MustGetErrMsg(fmt.Sprintf("drop binding for sql digest '%s'", "1"), "can't find any binding for '1'") tk.MustGetErrMsg(fmt.Sprintf("drop binding for sql digest '%s'", ""), "sql digest is empty") } - -func TestCreateBindingFromHistory(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t1(id int primary key, a int, b int, key(a))") - tk.MustExec("create table t2(id int primary key, a int, b int, key(a))") - - var testCases = []struct { - sqls []string - hint string - }{ - { - sqls: []string{ - "select %s * from t1, t2 where t1.id = t2.id", - "select %s * from test.t1, t2 where t1.id = t2.id", - "select %s * from test.t1, test.t2 where t1.id = t2.id", - "select %s * from t1, test.t2 where t1.id = t2.id", - }, - hint: "/*+ merge_join(t1, t2) */", - }, - { - sqls: []string{ - "select %s * from t1 where a = 1", - "select %s * from test.t1 where a = 1", - }, - hint: "/*+ ignore_index(t, a) */", - }, - } - - for _, testCase := range testCases { - for _, bind := range testCase.sqls { - stmtsummary.StmtSummaryByDigestMap.Clear() - bindSQL := fmt.Sprintf(bind, testCase.hint) - tk.MustExec(bindSQL) - planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", bindSQL)).Rows() - tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0])) - showRes := tk.MustQuery("show bindings").Rows() - require.Equal(t, len(showRes), 1) - require.Equal(t, planDigest[0][0], showRes[0][10]) - for _, sql := range testCase.sqls { - tk.MustExec(fmt.Sprintf(sql, "")) - tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) - } - } - showRes := tk.MustQuery("show bindings").Rows() - require.Equal(t, len(showRes), 1) - tk.MustExec(fmt.Sprintf("drop binding for sql digest '%s'", showRes[0][9])) - } - - // exception cases - tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", "1"), "can't find any plans for '1'") - tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", ""), "plan digest is empty") - tk.MustExec("create binding for select * from t1, t2 where t1.id = t2.id using select /*+ merge_join(t1, t2) */ * from t1, t2 where t1.id = t2.id") - showRes := tk.MustQuery("show bindings").Rows() - require.Equal(t, showRes[0][10], "") // plan digest should be nil by create for -} - -func TestCreateBindingForPrepareFromHistory(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(id int primary key, a int, key(a))") - - tk.MustExec("prepare stmt from 'select /*+ ignore_index(t,a) */ * from t where a = ?'") - tk.MustExec("set @a = 1") - tk.MustExec("execute stmt using @a") - planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", "select /*+ ignore_index(t,a) */ * from t where a = ? [arguments: 1]")).Rows() - showRes := tk.MustQuery("show bindings").Rows() - require.Equal(t, len(showRes), 0) - tk.MustExec(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0])) - showRes = tk.MustQuery("show bindings").Rows() - require.Equal(t, len(showRes), 1) - require.Equal(t, planDigest[0][0], showRes[0][10]) - tk.MustExec("execute stmt using @a") - tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) -} - -func TestErrorCasesCreateBindingFromHistory(t *testing.T) { - store := testkit.CreateMockStore(t) - tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t1, t2, t3") - tk.MustExec("create table t1(id int)") - tk.MustExec("create table t2(id int)") - tk.MustExec("create table t3(id int)") - - sql := "select * from t1 where t1.id in (select id from t2)" - tk.MustExec(sql) - planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() - tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with sub query") - - sql = "select * from t1, t2, t3 where t1.id = t2.id and t2.id = t3.id" - tk.MustExec(sql) - planDigest = tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() - tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with more than two table join") -} diff --git a/infoschema/cluster_tables_test.go b/infoschema/cluster_tables_test.go index 5e323b2adc88a..6acfb292afef7 100644 --- a/infoschema/cluster_tables_test.go +++ b/infoschema/cluster_tables_test.go @@ -48,6 +48,7 @@ import ( "github.com/pingcap/tidb/util/pdapi" "github.com/pingcap/tidb/util/resourcegrouptag" "github.com/pingcap/tidb/util/set" + "github.com/pingcap/tidb/util/stmtsummary" "github.com/pingcap/tipb/go-tipb" "github.com/stretchr/testify/require" "google.golang.org/grpc" @@ -852,3 +853,126 @@ func TestMDLView(t *testing.T) { wg.Wait() } + +func TestCreateBindingFromHistory(t *testing.T) { + s := new(clusterTablesSuite) + s.store, s.dom = testkit.CreateMockStoreAndDomain(t) + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil) + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + tk := s.newTestKitWithRoot(t) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t1(id int primary key, a int, b int, key(a))") + tk.MustExec("create table t2(id int primary key, a int, b int, key(a))") + + var testCases = []struct { + sqls []string + hint string + }{ + { + sqls: []string{ + "select %s * from t1, t2 where t1.id = t2.id", + "select %s * from test.t1, t2 where t1.id = t2.id", + "select %s * from test.t1, test.t2 where t1.id = t2.id", + "select %s * from t1, test.t2 where t1.id = t2.id", + }, + hint: "/*+ merge_join(t1, t2) */", + }, + { + sqls: []string{ + "select %s * from t1 where a = 1", + "select %s * from test.t1 where a = 1", + }, + hint: "/*+ ignore_index(t, a) */", + }, + } + + for _, testCase := range testCases { + for _, bind := range testCase.sqls { + stmtsummary.StmtSummaryByDigestMap.Clear() + bindSQL := fmt.Sprintf(bind, testCase.hint) + tk.MustExec(bindSQL) + planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", bindSQL)).Rows() + tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0])) + showRes := tk.MustQuery("show bindings").Rows() + require.Equal(t, len(showRes), 1) + require.Equal(t, planDigest[0][0], showRes[0][10]) + for _, sql := range testCase.sqls { + tk.MustExec(fmt.Sprintf(sql, "")) + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) + } + } + showRes := tk.MustQuery("show bindings").Rows() + require.Equal(t, len(showRes), 1) + tk.MustExec(fmt.Sprintf("drop binding for sql digest '%s'", showRes[0][9])) + } + + // exception cases + tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", "1"), "can't find any plans for '1'") + tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", ""), "plan digest is empty") + tk.MustExec("create binding for select * from t1, t2 where t1.id = t2.id using select /*+ merge_join(t1, t2) */ * from t1, t2 where t1.id = t2.id") + showRes := tk.MustQuery("show bindings").Rows() + require.Equal(t, showRes[0][10], "") // plan digest should be nil by create for +} + +func TestCreateBindingForPrepareFromHistory(t *testing.T) { + s := new(clusterTablesSuite) + s.store, s.dom = testkit.CreateMockStoreAndDomain(t) + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil) + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + tk := s.newTestKitWithRoot(t) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(id int primary key, a int, key(a))") + + tk.MustExec("prepare stmt from 'select /*+ ignore_index(t,a) */ * from t where a = ?'") + tk.MustExec("set @a = 1") + tk.MustExec("execute stmt using @a") + planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", "select /*+ ignore_index(t,a) */ * from t where a = ? [arguments: 1]")).Rows() + showRes := tk.MustQuery("show bindings").Rows() + require.Equal(t, len(showRes), 0) + tk.MustExec(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0])) + showRes = tk.MustQuery("show bindings").Rows() + require.Equal(t, len(showRes), 1) + require.Equal(t, planDigest[0][0], showRes[0][10]) + tk.MustExec("execute stmt using @a") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) +} + +func TestErrorCasesCreateBindingFromHistory(t *testing.T) { + s := new(clusterTablesSuite) + s.store, s.dom = testkit.CreateMockStoreAndDomain(t) + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil) + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + tk := s.newTestKitWithRoot(t) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2, t3") + tk.MustExec("create table t1(id int)") + tk.MustExec("create table t2(id int)") + tk.MustExec("create table t3(id int)") + + sql := "select * from t1 where t1.id in (select id from t2)" + tk.MustExec(sql) + planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() + tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with sub query") + + sql = "select * from t1, t2, t3 where t1.id = t2.id and t2.id = t3.id" + tk.MustExec(sql) + planDigest = tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() + tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with more than two table join") +} diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index faef8312178f7..a104f6f6ed848 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -1040,11 +1040,37 @@ func checkHintedSQL(sql, charset, collation, db string) error { return nil } +func fetchRecordFromClusterStmtSummary(sctx sessionctx.Context, planDigest string) ([]chunk.Row, error) { + ctx := kv.WithInternalSourceType(context.Background(), kv.InternalTxnBindInfo) + exec, _ := sctx.(sqlexec.SQLExecutor) + fields := "stmt_type, schema_name, digest_text, sample_user, prepared, query_sample_text, charset, collation, plan_hint" + sql := fmt.Sprintf("select %s from information_schema.cluster_statements_summary where plan_digest = '%s' union distinct ", fields, planDigest) + + fmt.Sprintf("select %s from information_schema.cluster_statements_summary_history where plan_digest = '%s' ", fields, planDigest) + rs, err := exec.ExecuteInternal(ctx, sql) + if rs == nil { + return nil, errors.New("can't find any plans for '" + planDigest + "'") + } + if err != nil { + return nil, err + } + + var rows []chunk.Row + defer terror.Call(rs.Close) + if rows, err = sqlexec.DrainRecordSet(ctx, rs, 8); err != nil { + return nil, err + } + return rows, nil +} + func (b *PlanBuilder) buildCreateBindPlanFromPlanDigest(v *ast.CreateBindingStmt) (Plan, error) { if v.PlanDigest == "" { return nil, errors.New("plan digest is empty") } - bindableStmt := stmtsummary.StmtSummaryByDigestMap.GetBindableStmtByPlanDigest(v.PlanDigest) + rows, err := fetchRecordFromClusterStmtSummary(b.ctx, v.PlanDigest) + if err != nil { + return nil, err + } + bindableStmt := stmtsummary.GetBindableStmtFromCluster(rows) if bindableStmt == nil { return nil, errors.New("can't find any plans for '" + v.PlanDigest + "'") } diff --git a/util/stmtsummary/statement_summary.go b/util/stmtsummary/statement_summary.go index 09dd9a57fa3a6..0ac60f70a1e4a 100644 --- a/util/stmtsummary/statement_summary.go +++ b/util/stmtsummary/statement_summary.go @@ -27,6 +27,7 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/kvcache" @@ -500,28 +501,24 @@ func (ssMap *stmtSummaryByDigestMap) maxSQLLength() int { return int(ssMap.optMaxSQLLength.Load()) } -func getBindableStmtByPlanDigest(ssbd *stmtSummaryByDigest, planDigest string) *BindableStmt { - ssbd.Lock() - defer ssbd.Unlock() - if ssbd.initialized && ssbd.planDigest == planDigest && ssbd.history.Len() > 0 && - (ssbd.stmtType == "Select" || ssbd.stmtType == "Delete" || ssbd.stmtType == "Update" || ssbd.stmtType == "Insert" || ssbd.stmtType == "Replace") { - ssElement := ssbd.history.Back().Value.(*stmtSummaryByDigestElement) - ssElement.Lock() - defer ssElement.Unlock() - // Empty auth users means that it is an internal queries. - if len(ssElement.authUsers) > 0 { +// GetBindableStmtFromCluster gets users' select/update/delete SQL. +func GetBindableStmtFromCluster(rows []chunk.Row) *BindableStmt { + for _, row := range rows { + user := row.GetString(3) + stmtType := row.GetString(0) + if user != "" && (stmtType == "Select" || stmtType == "Delete" || stmtType == "Update" || stmtType == "Insert" || stmtType == "Replace") { + // Empty auth users means that it is an internal queries. stmt := &BindableStmt{ - Schema: ssbd.schemaName, - Query: ssElement.sampleSQL, - PlanHint: ssElement.planHint, - Charset: ssElement.charset, - Collation: ssElement.collation, - Users: ssElement.authUsers, + Schema: row.GetString(1), //schemaName + Query: row.GetString(5), //sampleSQL + PlanHint: row.GetString(8), //planHint + Charset: row.GetString(6), //charset + Collation: row.GetString(7), //collation } // If it is SQL command prepare / execute, the ssElement.sampleSQL is `execute ...`, we should get the original select query. // If it is binary protocol prepare / execute, ssbd.normalizedSQL should be same as ssElement.sampleSQL. - if ssElement.prepared { - stmt.Query = ssbd.normalizedSQL + if row.GetInt64(4) == 1 { + stmt.Query = row.GetString(2) //normalizedSQL } return stmt } @@ -529,20 +526,6 @@ func getBindableStmtByPlanDigest(ssbd *stmtSummaryByDigest, planDigest string) * return nil } -// GetBindableStmtByPlanDigest gets users' select/update/delete SQL by plan digest. -func (ssMap *stmtSummaryByDigestMap) GetBindableStmtByPlanDigest(planDigest string) *BindableStmt { - ssMap.Lock() - values := ssMap.summaryMap.Values() - ssMap.Unlock() - - for _, value := range values { - if stmt := getBindableStmtByPlanDigest(value.(*stmtSummaryByDigest), planDigest); stmt != nil { - return stmt - } - } - return nil -} - // newStmtSummaryByDigest creates a stmtSummaryByDigest from StmtExecInfo. func (ssbd *stmtSummaryByDigest) init(sei *StmtExecInfo, _ int64, _ int64, _ int) { // Use "," to separate table names to support FIND_IN_SET. From 0affe2a4248d4e943590a4dfefab07a95f282f0a Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:30:52 +0800 Subject: [PATCH 06/16] fix ut --- executor/tiflashtest/tiflash_test.go | 22 ------------ infoschema/cluster_tables_test.go | 54 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 22 deletions(-) diff --git a/executor/tiflashtest/tiflash_test.go b/executor/tiflashtest/tiflash_test.go index ffd949ee28f66..2198182a8950e 100644 --- a/executor/tiflashtest/tiflash_test.go +++ b/executor/tiflashtest/tiflash_test.go @@ -29,7 +29,6 @@ import ( "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" - "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/mockstore/unistore" @@ -1257,24 +1256,3 @@ func TestTiflashEmptyDynamicPruneResult(t *testing.T) { tk.MustQuery("select /*+ read_from_storage(tiflash[t2]) */ * from IDT_RP24833 partition(p2) t2 where t2. col1 <= -8448770111093677011;").Check(testkit.Rows()) tk.MustQuery("select /*+ read_from_storage(tiflash[t1, t2]) */ * from IDT_RP24833 partition(p3, p4) t1 join IDT_RP24833 partition(p2) t2 on t1.col1 = t2.col1 where t1. col1 between -8448770111093677011 and -8448770111093677011 and t2. col1 <= -8448770111093677011;").Check(testkit.Rows()) } - -func TestBindingFromHistoryWithTiFlashBindable(t *testing.T) { - store := testkit.CreateMockStore(t, withMockTiFlash(2)) - tk := testkit.NewTestKit(t, store) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - tk.MustExec("use test;") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int);") - tk.MustExec("alter table test.t set tiflash replica 1") - tb := external.GetTableByName(t, tk, "test", "t") - err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) - require.NoError(t, err) - tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") - - sql := "select * from t" - tk.MustExec(sql) - rows := tk.MustQuery("explain select * from t").Rows() - fmt.Println(rows) - planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() - tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with tiflash engine") -} diff --git a/infoschema/cluster_tables_test.go b/infoschema/cluster_tables_test.go index 6acfb292afef7..452f9516c9fc8 100644 --- a/infoschema/cluster_tables_test.go +++ b/infoschema/cluster_tables_test.go @@ -31,6 +31,7 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/fn" "github.com/pingcap/kvproto/pkg/deadlock" + "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" @@ -42,8 +43,11 @@ import ( "github.com/pingcap/tidb/server" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/store/helper" + "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/mockstore/mockstorage" + "github.com/pingcap/tidb/store/mockstore/unistore" "github.com/pingcap/tidb/testkit" + "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/pdapi" "github.com/pingcap/tidb/util/resourcegrouptag" @@ -51,6 +55,7 @@ import ( "github.com/pingcap/tidb/util/stmtsummary" "github.com/pingcap/tipb/go-tipb" "github.com/stretchr/testify/require" + "github.com/tikv/client-go/v2/testutils" "google.golang.org/grpc" ) @@ -976,3 +981,52 @@ func TestErrorCasesCreateBindingFromHistory(t *testing.T) { planDigest = tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with more than two table join") } + +// withMockTiFlash sets the mockStore to have N TiFlash stores (naming as tiflash0, tiflash1, ...). +func withMockTiFlash(nodes int) mockstore.MockTiKVStoreOption { + return mockstore.WithMultipleOptions( + mockstore.WithClusterInspector(func(c testutils.Cluster) { + mockCluster := c.(*unistore.Cluster) + _, _, region1 := mockstore.BootstrapWithSingleStore(c) + tiflashIdx := 0 + for tiflashIdx < nodes { + store2 := c.AllocID() + peer2 := c.AllocID() + addr2 := fmt.Sprintf("tiflash%d", tiflashIdx) + mockCluster.AddStore(store2, addr2, &metapb.StoreLabel{Key: "engine", Value: "tiflash"}) + mockCluster.AddPeer(region1, store2, peer2) + tiflashIdx++ + } + }), + mockstore.WithStoreType(mockstore.EmbedUnistore), + ) +} + +func TestBindingFromHistoryWithTiFlashBindable(t *testing.T) { + s := new(clusterTablesSuite) + s.store, s.dom = testkit.CreateMockStoreAndDomain(t) + s.store = testkit.CreateMockStore(t, withMockTiFlash(2)) + s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil) + s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() + s.startTime = time.Now() + defer s.httpServer.Close() + defer s.rpcserver.Stop() + tk := s.newTestKitWithRoot(t) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + + tk.MustExec("use test;") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int);") + tk.MustExec("alter table test.t set tiflash replica 1") + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) + tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") + + sql := "select * from t" + tk.MustExec(sql) + rows := tk.MustQuery("explain select * from t").Rows() + fmt.Println(rows) + planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() + tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with tiflash engine") +} From dddf4804c25b29816be4c1933e2372cf4e3777d5 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Fri, 9 Dec 2022 10:14:11 +0800 Subject: [PATCH 07/16] bazel --- executor/tiflashtest/BUILD.bazel | 1 - infoschema/BUILD.bazel | 5 +++++ util/stmtsummary/BUILD.bazel | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/executor/tiflashtest/BUILD.bazel b/executor/tiflashtest/BUILD.bazel index fb8388109b737..5223fa79cc2d9 100644 --- a/executor/tiflashtest/BUILD.bazel +++ b/executor/tiflashtest/BUILD.bazel @@ -15,7 +15,6 @@ go_test( "//domain", "//executor", "//meta/autoid", - "//parser/auth", "//parser/terror", "//store/mockstore", "//store/mockstore/unistore", diff --git a/infoschema/BUILD.bazel b/infoschema/BUILD.bazel index 53bf35a2d43e3..37fd2bc423dc9 100644 --- a/infoschema/BUILD.bazel +++ b/infoschema/BUILD.bazel @@ -93,8 +93,10 @@ go_test( "//store/helper", "//store/mockstore", "//store/mockstore/mockstorage", + "//store/mockstore/unistore", "//table", "//testkit", + "//testkit/external", "//testkit/testsetup", "//testkit/testutil", "//types", @@ -104,14 +106,17 @@ go_test( "//util/pdapi", "//util/resourcegrouptag", "//util/set", + "//util/stmtsummary", "@com_github_gorilla_mux//:mux", "@com_github_pingcap_errors//:errors", "@com_github_pingcap_failpoint//:failpoint", "@com_github_pingcap_fn//:fn", "@com_github_pingcap_kvproto//pkg/deadlock", + "@com_github_pingcap_kvproto//pkg/metapb", "@com_github_pingcap_tipb//go-tipb", "@com_github_prometheus_prometheus//promql", "@com_github_stretchr_testify//require", + "@com_github_tikv_client_go_v2//testutils", "@org_golang_google_grpc//:grpc", "@org_uber_go_goleak//:goleak", ], diff --git a/util/stmtsummary/BUILD.bazel b/util/stmtsummary/BUILD.bazel index 7c85e57d52aee..3c8c295a5d659 100644 --- a/util/stmtsummary/BUILD.bazel +++ b/util/stmtsummary/BUILD.bazel @@ -15,6 +15,7 @@ go_library( "//parser/mysql", "//sessionctx/stmtctx", "//types", + "//util/chunk", "//util/execdetails", "//util/hack", "//util/kvcache", From 107d649a6bb795c11b30e19307ad34890df7e026 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Fri, 9 Dec 2022 11:05:25 +0800 Subject: [PATCH 08/16] order by length(plan_hint) --- planner/core/planbuilder.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 0d8a611c10566..700a6d56f38e7 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -1045,7 +1045,8 @@ func fetchRecordFromClusterStmtSummary(sctx sessionctx.Context, planDigest strin exec, _ := sctx.(sqlexec.SQLExecutor) fields := "stmt_type, schema_name, digest_text, sample_user, prepared, query_sample_text, charset, collation, plan_hint" sql := fmt.Sprintf("select %s from information_schema.cluster_statements_summary where plan_digest = '%s' union distinct ", fields, planDigest) + - fmt.Sprintf("select %s from information_schema.cluster_statements_summary_history where plan_digest = '%s' ", fields, planDigest) + fmt.Sprintf("select %s from information_schema.cluster_statements_summary_history where plan_digest = '%s' ", fields, planDigest) + + "order by length(plan_digest) desc" rs, err := exec.ExecuteInternal(ctx, sql) if rs == nil { return nil, errors.New("can't find any plans for '" + planDigest + "'") From ca5a09429e107aa6dcaa47ffb1318a907b59b137 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Mon, 12 Dec 2022 15:33:42 +0800 Subject: [PATCH 09/16] Update planbuilder.go --- planner/core/planbuilder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 700a6d56f38e7..7a1e502b83e94 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -1049,7 +1049,7 @@ func fetchRecordFromClusterStmtSummary(sctx sessionctx.Context, planDigest strin "order by length(plan_digest) desc" rs, err := exec.ExecuteInternal(ctx, sql) if rs == nil { - return nil, errors.New("can't find any plans for '" + planDigest + "'") + return nil, errors.New("cluster can't find any plans for '" + planDigest + "'") } if err != nil { return nil, err From 102270b953aea12366d7d9218a74d79c862554a6 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Mon, 12 Dec 2022 15:36:55 +0800 Subject: [PATCH 10/16] Revert "Update planbuilder.go" This reverts commit ca5a09429e107aa6dcaa47ffb1318a907b59b137. --- planner/core/planbuilder.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 7a1e502b83e94..700a6d56f38e7 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -1049,7 +1049,7 @@ func fetchRecordFromClusterStmtSummary(sctx sessionctx.Context, planDigest strin "order by length(plan_digest) desc" rs, err := exec.ExecuteInternal(ctx, sql) if rs == nil { - return nil, errors.New("cluster can't find any plans for '" + planDigest + "'") + return nil, errors.New("can't find any plans for '" + planDigest + "'") } if err != nil { return nil, err From 44b7926aa370e379181568f23c6b7e5148412a31 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Mon, 12 Dec 2022 15:46:07 +0800 Subject: [PATCH 11/16] commit --- bindinfo/bind_test.go | 105 +++++++++++++++ cmd/explaintest/r/index_merge.result | 6 +- executor/tiflashtest/tiflash_test.go | 22 ++++ infoschema/cluster_tables_test.go | 178 -------------------------- planner/core/planbuilder.go | 29 +---- util/stmtsummary/statement_summary.go | 47 ++++--- 6 files changed, 163 insertions(+), 224 deletions(-) diff --git a/bindinfo/bind_test.go b/bindinfo/bind_test.go index cb8e62687df8f..052e5ecab2b18 100644 --- a/bindinfo/bind_test.go +++ b/bindinfo/bind_test.go @@ -1388,3 +1388,108 @@ func TestDropBindBySQLDigest(t *testing.T) { tk.MustGetErrMsg(fmt.Sprintf("drop binding for sql digest '%s'", "1"), "can't find any binding for '1'") tk.MustGetErrMsg(fmt.Sprintf("drop binding for sql digest '%s'", ""), "sql digest is empty") } + +func TestCreateBindingFromHistory(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t1(id int primary key, a int, b int, key(a))") + tk.MustExec("create table t2(id int primary key, a int, b int, key(a))") + + var testCases = []struct { + sqls []string + hint string + }{ + { + sqls: []string{ + "select %s * from t1, t2 where t1.id = t2.id", + "select %s * from test.t1, t2 where t1.id = t2.id", + "select %s * from test.t1, test.t2 where t1.id = t2.id", + "select %s * from t1, test.t2 where t1.id = t2.id", + }, + hint: "/*+ merge_join(t1, t2) */", + }, + { + sqls: []string{ + "select %s * from t1 where a = 1", + "select %s * from test.t1 where a = 1", + }, + hint: "/*+ ignore_index(t, a) */", + }, + } + + for _, testCase := range testCases { + for _, bind := range testCase.sqls { + stmtsummary.StmtSummaryByDigestMap.Clear() + bindSQL := fmt.Sprintf(bind, testCase.hint) + tk.MustExec(bindSQL) + planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", bindSQL)).Rows() + tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0])) + showRes := tk.MustQuery("show bindings").Rows() + require.Equal(t, len(showRes), 1) + require.Equal(t, planDigest[0][0], showRes[0][10]) + for _, sql := range testCase.sqls { + tk.MustExec(fmt.Sprintf(sql, "")) + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) + } + } + showRes := tk.MustQuery("show bindings").Rows() + require.Equal(t, len(showRes), 1) + tk.MustExec(fmt.Sprintf("drop binding for sql digest '%s'", showRes[0][9])) + } + + // exception cases + tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", "1"), "can't find any plans for '1'") + tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", ""), "plan digest is empty") + tk.MustExec("create binding for select * from t1, t2 where t1.id = t2.id using select /*+ merge_join(t1, t2) */ * from t1, t2 where t1.id = t2.id") + showRes := tk.MustQuery("show bindings").Rows() + require.Equal(t, showRes[0][10], "") // plan digest should be nil by create for +} + +func TestCreateBindingForPrepareFromHistory(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(id int primary key, a int, key(a))") + + tk.MustExec("prepare stmt from 'select /*+ ignore_index(t,a) */ * from t where a = ?'") + tk.MustExec("set @a = 1") + tk.MustExec("execute stmt using @a") + planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", "select /*+ ignore_index(t,a) */ * from t where a = ? [arguments: 1]")).Rows() + showRes := tk.MustQuery("show bindings").Rows() + require.Equal(t, len(showRes), 0) + tk.MustExec(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0])) + showRes = tk.MustQuery("show bindings").Rows() + require.Equal(t, len(showRes), 1) + require.Equal(t, planDigest[0][0], showRes[0][10]) + tk.MustExec("execute stmt using @a") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) +} + +func TestErrorCasesCreateBindingFromHistory(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + + tk.MustExec("use test") + tk.MustExec("drop table if exists t1, t2, t3") + tk.MustExec("create table t1(id int)") + tk.MustExec("create table t2(id int)") + tk.MustExec("create table t3(id int)") + + sql := "select * from t1 where t1.id in (select id from t2)" + tk.MustExec(sql) + planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() + tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with sub query") + + sql = "select * from t1, t2, t3 where t1.id = t2.id and t2.id = t3.id" + tk.MustExec(sql) + planDigest = tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() + tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with more than two table join") +} diff --git a/cmd/explaintest/r/index_merge.result b/cmd/explaintest/r/index_merge.result index 6b44c6122987e..0233dbdb55f52 100644 --- a/cmd/explaintest/r/index_merge.result +++ b/cmd/explaintest/r/index_merge.result @@ -455,9 +455,9 @@ c1 c2 c3 ///// MEMORY Table explain select count(c1) from (select /*+ use_index_merge(t_alias), stream_agg() */ count(1) c1 from information_schema.statements_summary where sum_latency >= 0 or max_latency >= 0 order by 1) dt; id estRows task access object operator info -StreamAgg_10 1.00 root funcs:count(Column#96)->Column#97 -└─Sort_11 1.00 root Column#96 - └─StreamAgg_14 1.00 root funcs:count(1)->Column#96 +StreamAgg_10 1.00 root funcs:count(Column#93)->Column#94 +└─Sort_11 1.00 root Column#93 + └─StreamAgg_14 1.00 root funcs:count(1)->Column#93 └─MemTableScan_18 10000.00 root table:STATEMENTS_SUMMARY show warnings; Level Code Message diff --git a/executor/tiflashtest/tiflash_test.go b/executor/tiflashtest/tiflash_test.go index 222e1bfdaff0b..a21de05a76a22 100644 --- a/executor/tiflashtest/tiflash_test.go +++ b/executor/tiflashtest/tiflash_test.go @@ -17,6 +17,7 @@ package tiflashtest import ( "bytes" "fmt" + "github.com/pingcap/tidb/parser/auth" "math/rand" "strings" "sync" @@ -1258,6 +1259,27 @@ func TestTiflashEmptyDynamicPruneResult(t *testing.T) { tk.MustQuery("select /*+ read_from_storage(tiflash[t1, t2]) */ * from IDT_RP24833 partition(p3, p4) t1 join IDT_RP24833 partition(p2) t2 on t1.col1 = t2.col1 where t1. col1 between -8448770111093677011 and -8448770111093677011 and t2. col1 <= -8448770111093677011;").Check(testkit.Rows()) } +func TestBindingFromHistoryWithTiFlashBindable(t *testing.T) { + store := testkit.CreateMockStore(t, withMockTiFlash(2)) + tk := testkit.NewTestKit(t, store) + require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) + tk.MustExec("use test;") + tk.MustExec("drop table if exists t;") + tk.MustExec("create table t(a int);") + tk.MustExec("alter table test.t set tiflash replica 1") + tb := external.GetTableByName(t, tk, "test", "t") + err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) + require.NoError(t, err) + tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") + + sql := "select * from t" + tk.MustExec(sql) + rows := tk.MustQuery("explain select * from t").Rows() + fmt.Println(rows) + planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() + tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with tiflash engine") +} + func TestDisaggregatedTiFlash(t *testing.T) { config.UpdateGlobal(func(conf *config.Config) { conf.DisaggregatedTiFlash = true diff --git a/infoschema/cluster_tables_test.go b/infoschema/cluster_tables_test.go index 452f9516c9fc8..5e323b2adc88a 100644 --- a/infoschema/cluster_tables_test.go +++ b/infoschema/cluster_tables_test.go @@ -31,7 +31,6 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/fn" "github.com/pingcap/kvproto/pkg/deadlock" - "github.com/pingcap/kvproto/pkg/metapb" "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" @@ -43,19 +42,14 @@ import ( "github.com/pingcap/tidb/server" "github.com/pingcap/tidb/sessionctx/variable" "github.com/pingcap/tidb/store/helper" - "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/mockstore/mockstorage" - "github.com/pingcap/tidb/store/mockstore/unistore" "github.com/pingcap/tidb/testkit" - "github.com/pingcap/tidb/testkit/external" "github.com/pingcap/tidb/util" "github.com/pingcap/tidb/util/pdapi" "github.com/pingcap/tidb/util/resourcegrouptag" "github.com/pingcap/tidb/util/set" - "github.com/pingcap/tidb/util/stmtsummary" "github.com/pingcap/tipb/go-tipb" "github.com/stretchr/testify/require" - "github.com/tikv/client-go/v2/testutils" "google.golang.org/grpc" ) @@ -858,175 +852,3 @@ func TestMDLView(t *testing.T) { wg.Wait() } - -func TestCreateBindingFromHistory(t *testing.T) { - s := new(clusterTablesSuite) - s.store, s.dom = testkit.CreateMockStoreAndDomain(t) - s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil) - s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() - s.startTime = time.Now() - defer s.httpServer.Close() - defer s.rpcserver.Stop() - tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t1(id int primary key, a int, b int, key(a))") - tk.MustExec("create table t2(id int primary key, a int, b int, key(a))") - - var testCases = []struct { - sqls []string - hint string - }{ - { - sqls: []string{ - "select %s * from t1, t2 where t1.id = t2.id", - "select %s * from test.t1, t2 where t1.id = t2.id", - "select %s * from test.t1, test.t2 where t1.id = t2.id", - "select %s * from t1, test.t2 where t1.id = t2.id", - }, - hint: "/*+ merge_join(t1, t2) */", - }, - { - sqls: []string{ - "select %s * from t1 where a = 1", - "select %s * from test.t1 where a = 1", - }, - hint: "/*+ ignore_index(t, a) */", - }, - } - - for _, testCase := range testCases { - for _, bind := range testCase.sqls { - stmtsummary.StmtSummaryByDigestMap.Clear() - bindSQL := fmt.Sprintf(bind, testCase.hint) - tk.MustExec(bindSQL) - planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", bindSQL)).Rows() - tk.MustExec(fmt.Sprintf("create session binding from history using plan digest '%s'", planDigest[0][0])) - showRes := tk.MustQuery("show bindings").Rows() - require.Equal(t, len(showRes), 1) - require.Equal(t, planDigest[0][0], showRes[0][10]) - for _, sql := range testCase.sqls { - tk.MustExec(fmt.Sprintf(sql, "")) - tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) - } - } - showRes := tk.MustQuery("show bindings").Rows() - require.Equal(t, len(showRes), 1) - tk.MustExec(fmt.Sprintf("drop binding for sql digest '%s'", showRes[0][9])) - } - - // exception cases - tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", "1"), "can't find any plans for '1'") - tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", ""), "plan digest is empty") - tk.MustExec("create binding for select * from t1, t2 where t1.id = t2.id using select /*+ merge_join(t1, t2) */ * from t1, t2 where t1.id = t2.id") - showRes := tk.MustQuery("show bindings").Rows() - require.Equal(t, showRes[0][10], "") // plan digest should be nil by create for -} - -func TestCreateBindingForPrepareFromHistory(t *testing.T) { - s := new(clusterTablesSuite) - s.store, s.dom = testkit.CreateMockStoreAndDomain(t) - s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil) - s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() - s.startTime = time.Now() - defer s.httpServer.Close() - defer s.rpcserver.Stop() - tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t") - tk.MustExec("create table t(id int primary key, a int, key(a))") - - tk.MustExec("prepare stmt from 'select /*+ ignore_index(t,a) */ * from t where a = ?'") - tk.MustExec("set @a = 1") - tk.MustExec("execute stmt using @a") - planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", "select /*+ ignore_index(t,a) */ * from t where a = ? [arguments: 1]")).Rows() - showRes := tk.MustQuery("show bindings").Rows() - require.Equal(t, len(showRes), 0) - tk.MustExec(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0])) - showRes = tk.MustQuery("show bindings").Rows() - require.Equal(t, len(showRes), 1) - require.Equal(t, planDigest[0][0], showRes[0][10]) - tk.MustExec("execute stmt using @a") - tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) -} - -func TestErrorCasesCreateBindingFromHistory(t *testing.T) { - s := new(clusterTablesSuite) - s.store, s.dom = testkit.CreateMockStoreAndDomain(t) - s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil) - s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() - s.startTime = time.Now() - defer s.httpServer.Close() - defer s.rpcserver.Stop() - tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - - tk.MustExec("use test") - tk.MustExec("drop table if exists t1, t2, t3") - tk.MustExec("create table t1(id int)") - tk.MustExec("create table t2(id int)") - tk.MustExec("create table t3(id int)") - - sql := "select * from t1 where t1.id in (select id from t2)" - tk.MustExec(sql) - planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() - tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with sub query") - - sql = "select * from t1, t2, t3 where t1.id = t2.id and t2.id = t3.id" - tk.MustExec(sql) - planDigest = tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() - tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with more than two table join") -} - -// withMockTiFlash sets the mockStore to have N TiFlash stores (naming as tiflash0, tiflash1, ...). -func withMockTiFlash(nodes int) mockstore.MockTiKVStoreOption { - return mockstore.WithMultipleOptions( - mockstore.WithClusterInspector(func(c testutils.Cluster) { - mockCluster := c.(*unistore.Cluster) - _, _, region1 := mockstore.BootstrapWithSingleStore(c) - tiflashIdx := 0 - for tiflashIdx < nodes { - store2 := c.AllocID() - peer2 := c.AllocID() - addr2 := fmt.Sprintf("tiflash%d", tiflashIdx) - mockCluster.AddStore(store2, addr2, &metapb.StoreLabel{Key: "engine", Value: "tiflash"}) - mockCluster.AddPeer(region1, store2, peer2) - tiflashIdx++ - } - }), - mockstore.WithStoreType(mockstore.EmbedUnistore), - ) -} - -func TestBindingFromHistoryWithTiFlashBindable(t *testing.T) { - s := new(clusterTablesSuite) - s.store, s.dom = testkit.CreateMockStoreAndDomain(t) - s.store = testkit.CreateMockStore(t, withMockTiFlash(2)) - s.rpcserver, s.listenAddr = s.setUpRPCService(t, "127.0.0.1:0", nil) - s.httpServer, s.mockAddr = s.setUpMockPDHTTPServer() - s.startTime = time.Now() - defer s.httpServer.Close() - defer s.rpcserver.Stop() - tk := s.newTestKitWithRoot(t) - require.NoError(t, tk.Session().Auth(&auth.UserIdentity{Username: "root", Hostname: "%"}, nil, nil)) - - tk.MustExec("use test;") - tk.MustExec("drop table if exists t;") - tk.MustExec("create table t(a int);") - tk.MustExec("alter table test.t set tiflash replica 1") - tb := external.GetTableByName(t, tk, "test", "t") - err := domain.GetDomain(tk.Session()).DDL().UpdateTableReplicaInfo(tk.Session(), tb.Meta().ID, true) - require.NoError(t, err) - tk.MustExec("set @@session.tidb_isolation_read_engines = 'tiflash'") - - sql := "select * from t" - tk.MustExec(sql) - rows := tk.MustQuery("explain select * from t").Rows() - fmt.Println(rows) - planDigest := tk.MustQuery(fmt.Sprintf("select plan_digest from information_schema.statements_summary where query_sample_text = '%s'", sql)).Rows() - tk.MustGetErrMsg(fmt.Sprintf("create binding from history using plan digest '%s'", planDigest[0][0]), "can't create binding for query with tiflash engine") -} diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go index 700a6d56f38e7..d8677ea7dd072 100644 --- a/planner/core/planbuilder.go +++ b/planner/core/planbuilder.go @@ -1040,38 +1040,11 @@ func checkHintedSQL(sql, charset, collation, db string) error { return nil } -func fetchRecordFromClusterStmtSummary(sctx sessionctx.Context, planDigest string) ([]chunk.Row, error) { - ctx := kv.WithInternalSourceType(context.Background(), kv.InternalTxnBindInfo) - exec, _ := sctx.(sqlexec.SQLExecutor) - fields := "stmt_type, schema_name, digest_text, sample_user, prepared, query_sample_text, charset, collation, plan_hint" - sql := fmt.Sprintf("select %s from information_schema.cluster_statements_summary where plan_digest = '%s' union distinct ", fields, planDigest) + - fmt.Sprintf("select %s from information_schema.cluster_statements_summary_history where plan_digest = '%s' ", fields, planDigest) + - "order by length(plan_digest) desc" - rs, err := exec.ExecuteInternal(ctx, sql) - if rs == nil { - return nil, errors.New("can't find any plans for '" + planDigest + "'") - } - if err != nil { - return nil, err - } - - var rows []chunk.Row - defer terror.Call(rs.Close) - if rows, err = sqlexec.DrainRecordSet(ctx, rs, 8); err != nil { - return nil, err - } - return rows, nil -} - func (b *PlanBuilder) buildCreateBindPlanFromPlanDigest(v *ast.CreateBindingStmt) (Plan, error) { if v.PlanDigest == "" { return nil, errors.New("plan digest is empty") } - rows, err := fetchRecordFromClusterStmtSummary(b.ctx, v.PlanDigest) - if err != nil { - return nil, err - } - bindableStmt := stmtsummary.GetBindableStmtFromCluster(rows) + bindableStmt := stmtsummary.StmtSummaryByDigestMap.GetBindableStmtByPlanDigest(v.PlanDigest) if bindableStmt == nil { return nil, errors.New("can't find any plans for '" + v.PlanDigest + "'") } diff --git a/util/stmtsummary/statement_summary.go b/util/stmtsummary/statement_summary.go index 0ac60f70a1e4a..09dd9a57fa3a6 100644 --- a/util/stmtsummary/statement_summary.go +++ b/util/stmtsummary/statement_summary.go @@ -27,7 +27,6 @@ import ( "github.com/pingcap/failpoint" "github.com/pingcap/tidb/sessionctx/stmtctx" - "github.com/pingcap/tidb/util/chunk" "github.com/pingcap/tidb/util/execdetails" "github.com/pingcap/tidb/util/hack" "github.com/pingcap/tidb/util/kvcache" @@ -501,24 +500,28 @@ func (ssMap *stmtSummaryByDigestMap) maxSQLLength() int { return int(ssMap.optMaxSQLLength.Load()) } -// GetBindableStmtFromCluster gets users' select/update/delete SQL. -func GetBindableStmtFromCluster(rows []chunk.Row) *BindableStmt { - for _, row := range rows { - user := row.GetString(3) - stmtType := row.GetString(0) - if user != "" && (stmtType == "Select" || stmtType == "Delete" || stmtType == "Update" || stmtType == "Insert" || stmtType == "Replace") { - // Empty auth users means that it is an internal queries. +func getBindableStmtByPlanDigest(ssbd *stmtSummaryByDigest, planDigest string) *BindableStmt { + ssbd.Lock() + defer ssbd.Unlock() + if ssbd.initialized && ssbd.planDigest == planDigest && ssbd.history.Len() > 0 && + (ssbd.stmtType == "Select" || ssbd.stmtType == "Delete" || ssbd.stmtType == "Update" || ssbd.stmtType == "Insert" || ssbd.stmtType == "Replace") { + ssElement := ssbd.history.Back().Value.(*stmtSummaryByDigestElement) + ssElement.Lock() + defer ssElement.Unlock() + // Empty auth users means that it is an internal queries. + if len(ssElement.authUsers) > 0 { stmt := &BindableStmt{ - Schema: row.GetString(1), //schemaName - Query: row.GetString(5), //sampleSQL - PlanHint: row.GetString(8), //planHint - Charset: row.GetString(6), //charset - Collation: row.GetString(7), //collation + Schema: ssbd.schemaName, + Query: ssElement.sampleSQL, + PlanHint: ssElement.planHint, + Charset: ssElement.charset, + Collation: ssElement.collation, + Users: ssElement.authUsers, } // If it is SQL command prepare / execute, the ssElement.sampleSQL is `execute ...`, we should get the original select query. // If it is binary protocol prepare / execute, ssbd.normalizedSQL should be same as ssElement.sampleSQL. - if row.GetInt64(4) == 1 { - stmt.Query = row.GetString(2) //normalizedSQL + if ssElement.prepared { + stmt.Query = ssbd.normalizedSQL } return stmt } @@ -526,6 +529,20 @@ func GetBindableStmtFromCluster(rows []chunk.Row) *BindableStmt { return nil } +// GetBindableStmtByPlanDigest gets users' select/update/delete SQL by plan digest. +func (ssMap *stmtSummaryByDigestMap) GetBindableStmtByPlanDigest(planDigest string) *BindableStmt { + ssMap.Lock() + values := ssMap.summaryMap.Values() + ssMap.Unlock() + + for _, value := range values { + if stmt := getBindableStmtByPlanDigest(value.(*stmtSummaryByDigest), planDigest); stmt != nil { + return stmt + } + } + return nil +} + // newStmtSummaryByDigest creates a stmtSummaryByDigest from StmtExecInfo. func (ssbd *stmtSummaryByDigest) init(sei *StmtExecInfo, _ int64, _ int64, _ int) { // Use "," to separate table names to support FIND_IN_SET. From 99ff24fe68b8402a65395b49bd2463da0ef6a622 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Mon, 12 Dec 2022 15:47:53 +0800 Subject: [PATCH 12/16] commit --- executor/tiflashtest/BUILD.bazel | 1 + infoschema/BUILD.bazel | 5 ----- util/stmtsummary/BUILD.bazel | 1 - 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/executor/tiflashtest/BUILD.bazel b/executor/tiflashtest/BUILD.bazel index 5223fa79cc2d9..fb8388109b737 100644 --- a/executor/tiflashtest/BUILD.bazel +++ b/executor/tiflashtest/BUILD.bazel @@ -15,6 +15,7 @@ go_test( "//domain", "//executor", "//meta/autoid", + "//parser/auth", "//parser/terror", "//store/mockstore", "//store/mockstore/unistore", diff --git a/infoschema/BUILD.bazel b/infoschema/BUILD.bazel index 37fd2bc423dc9..53bf35a2d43e3 100644 --- a/infoschema/BUILD.bazel +++ b/infoschema/BUILD.bazel @@ -93,10 +93,8 @@ go_test( "//store/helper", "//store/mockstore", "//store/mockstore/mockstorage", - "//store/mockstore/unistore", "//table", "//testkit", - "//testkit/external", "//testkit/testsetup", "//testkit/testutil", "//types", @@ -106,17 +104,14 @@ go_test( "//util/pdapi", "//util/resourcegrouptag", "//util/set", - "//util/stmtsummary", "@com_github_gorilla_mux//:mux", "@com_github_pingcap_errors//:errors", "@com_github_pingcap_failpoint//:failpoint", "@com_github_pingcap_fn//:fn", "@com_github_pingcap_kvproto//pkg/deadlock", - "@com_github_pingcap_kvproto//pkg/metapb", "@com_github_pingcap_tipb//go-tipb", "@com_github_prometheus_prometheus//promql", "@com_github_stretchr_testify//require", - "@com_github_tikv_client_go_v2//testutils", "@org_golang_google_grpc//:grpc", "@org_uber_go_goleak//:goleak", ], diff --git a/util/stmtsummary/BUILD.bazel b/util/stmtsummary/BUILD.bazel index 3c8c295a5d659..7c85e57d52aee 100644 --- a/util/stmtsummary/BUILD.bazel +++ b/util/stmtsummary/BUILD.bazel @@ -15,7 +15,6 @@ go_library( "//parser/mysql", "//sessionctx/stmtctx", "//types", - "//util/chunk", "//util/execdetails", "//util/hack", "//util/kvcache", From f65c0e5e3177e674370bf906ac6b0369edb2c36a Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Mon, 12 Dec 2022 15:48:51 +0800 Subject: [PATCH 13/16] Update tiflash_test.go --- executor/tiflashtest/tiflash_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executor/tiflashtest/tiflash_test.go b/executor/tiflashtest/tiflash_test.go index a21de05a76a22..baba133b3d5a7 100644 --- a/executor/tiflashtest/tiflash_test.go +++ b/executor/tiflashtest/tiflash_test.go @@ -17,7 +17,6 @@ package tiflashtest import ( "bytes" "fmt" - "github.com/pingcap/tidb/parser/auth" "math/rand" "strings" "sync" @@ -31,6 +30,7 @@ import ( "github.com/pingcap/tidb/config" "github.com/pingcap/tidb/domain" "github.com/pingcap/tidb/executor" + "github.com/pingcap/tidb/parser/auth" "github.com/pingcap/tidb/parser/terror" "github.com/pingcap/tidb/store/mockstore" "github.com/pingcap/tidb/store/mockstore/unistore" From 708d1ec4c29100f58ee82263d180994c6cdfbef5 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Mon, 12 Dec 2022 15:56:36 +0800 Subject: [PATCH 14/16] Update tables_test.go --- infoschema/tables_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/infoschema/tables_test.go b/infoschema/tables_test.go index 23075793b1641..26297b6daf922 100644 --- a/infoschema/tables_test.go +++ b/infoschema/tables_test.go @@ -1678,7 +1678,7 @@ func TestAddFieldsForBinding(t *testing.T) { tk.MustExec("create table t(a int, key(a))") tk.MustExec("select /*+ ignore_index(t, a)*/ * from t where a = 1") planDigest := "4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb" - rows := tk.MustQuery(fmt.Sprintf("select stmt_type, prepared, sample_user, schema_name, query_sample_text, charset, collation, plan_hint "+ + rows := tk.MustQuery(fmt.Sprintf("select stmt_type, prepared, sample_user, schema_name, query_sample_text, charset, collation, plan_hint, digest_text "+ "from information_schema.cluster_statements_summary where plan_digest = '%s'", planDigest)).Rows() require.Equal(t, rows[0][0], "Select") @@ -1689,5 +1689,6 @@ func TestAddFieldsForBinding(t *testing.T) { require.Equal(t, rows[0][5], "utf8mb4") require.Equal(t, rows[0][6], "utf8mb4_bin") require.Equal(t, rows[0][7], "use_index(@`sel_1` `test`.`t` ), ignore_index(`t` `a`)") + require.Equal(t, rows[0][8], "select * from `t` where `a` = ?") fmt.Println(planDigest) } From 08ca1ea4eade2c424e24c48934a37def778c64f2 Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Mon, 12 Dec 2022 18:30:10 +0800 Subject: [PATCH 15/16] Update tables_test.go --- infoschema/tables_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/infoschema/tables_test.go b/infoschema/tables_test.go index 26297b6daf922..ebf3e9b535893 100644 --- a/infoschema/tables_test.go +++ b/infoschema/tables_test.go @@ -1690,5 +1690,4 @@ func TestAddFieldsForBinding(t *testing.T) { require.Equal(t, rows[0][6], "utf8mb4_bin") require.Equal(t, rows[0][7], "use_index(@`sel_1` `test`.`t` ), ignore_index(`t` `a`)") require.Equal(t, rows[0][8], "select * from `t` where `a` = ?") - fmt.Println(planDigest) } From 251dfe4b7b86ae5d88367fc17f8741102cd2ed0c Mon Sep 17 00:00:00 2001 From: fzzf678 <108643977+fzzf678@users.noreply.github.com> Date: Mon, 12 Dec 2022 19:31:38 +0800 Subject: [PATCH 16/16] Update index_merge.result --- cmd/explaintest/r/index_merge.result | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/explaintest/r/index_merge.result b/cmd/explaintest/r/index_merge.result index 0233dbdb55f52..6b44c6122987e 100644 --- a/cmd/explaintest/r/index_merge.result +++ b/cmd/explaintest/r/index_merge.result @@ -455,9 +455,9 @@ c1 c2 c3 ///// MEMORY Table explain select count(c1) from (select /*+ use_index_merge(t_alias), stream_agg() */ count(1) c1 from information_schema.statements_summary where sum_latency >= 0 or max_latency >= 0 order by 1) dt; id estRows task access object operator info -StreamAgg_10 1.00 root funcs:count(Column#93)->Column#94 -└─Sort_11 1.00 root Column#93 - └─StreamAgg_14 1.00 root funcs:count(1)->Column#93 +StreamAgg_10 1.00 root funcs:count(Column#96)->Column#97 +└─Sort_11 1.00 root Column#96 + └─StreamAgg_14 1.00 root funcs:count(1)->Column#96 └─MemTableScan_18 10000.00 root table:STATEMENTS_SUMMARY show warnings; Level Code Message