Skip to content

Commit

Permalink
Merge branch 'master' into add-index-clone-dt
Browse files Browse the repository at this point in the history
  • Loading branch information
tangenta committed Nov 30, 2022
2 parents f483811 + a48fe79 commit 8bda001
Show file tree
Hide file tree
Showing 98 changed files with 4,240 additions and 1,147 deletions.
8 changes: 4 additions & 4 deletions DEPS.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -2915,8 +2915,8 @@ def go_deps():
name = "com_github_pingcap_kvproto",
build_file_proto_mode = "disable_global",
importpath = "github.com/pingcap/kvproto",
sum = "h1:hnUlIU5nCH6PAO9DC5DhODX1cwqoTcXTNIODyvNI9q4=",
version = "v0.0.0-20221123043343-cdc67325f05f",
sum = "h1:LzIZsQpXQlj8yF7+yvyOg680OaPq7bmPuDuszgXfHsw=",
version = "v0.0.0-20221129023506-621ec37aac7a",
)
go_repository(
name = "com_github_pingcap_log",
Expand Down Expand Up @@ -3519,8 +3519,8 @@ def go_deps():
name = "com_github_tikv_client_go_v2",
build_file_proto_mode = "disable_global",
importpath = "github.com/tikv/client-go/v2",
sum = "h1:nfdLYzkmYR2b0XurXSXcVFk06eO//P4VtkqoADX2tR4=",
version = "v2.0.3-0.20221128025602-81939ec8b2bb",
sum = "h1:vlgZedcfExiTzB3BB4nt5CpaghDfm9La/0Ofn7weIUA=",
version = "v2.0.3-0.20221129032117-857772dd0907",
)
go_repository(
name = "com_github_tikv_pd_client",
Expand Down
14 changes: 7 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ bazel_coverage_test: failpoint-enable bazel_ci_prepare

bazel_build: bazel_ci_prepare
mkdir -p bin
bazel $(BAZEL_GLOBAL_CONFIG) build $(BAZEL_CMD_CONFIG) --remote_download_minimal \
bazel $(BAZEL_GLOBAL_CONFIG) build $(BAZEL_CMD_CONFIG) \
//... --//build:with_nogo_flag=true
bazel $(BAZEL_GLOBAL_CONFIG) build $(BAZEL_CMD_CONFIG) \
//cmd/importer:importer //tidb-server:tidb-server //tidb-server:tidb-server-check --//build:with_nogo_flag=true
Expand All @@ -442,27 +442,27 @@ bazel_golangcilinter:
-- run $$($(PACKAGE_DIRECTORIES)) --config ./.golangci.yaml

bazel_brietest: failpoint-enable bazel_ci_prepare
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --remote_download_minimal --test_arg=-with-real-tikv \
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --test_arg=-with-real-tikv \
-- //tests/realtikvtest/brietest/...

bazel_pessimistictest: failpoint-enable bazel_ci_prepare
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --remote_download_minimal --test_arg=-with-real-tikv \
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --test_arg=-with-real-tikv \
-- //tests/realtikvtest/pessimistictest/...

bazel_sessiontest: failpoint-enable bazel_ci_prepare
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --remote_download_minimal --test_arg=-with-real-tikv \
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --test_arg=-with-real-tikv \
-- //tests/realtikvtest/sessiontest/...

bazel_statisticstest: failpoint-enable bazel_ci_prepare
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --remote_download_minimal --test_arg=-with-real-tikv \
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --test_arg=-with-real-tikv \
-- //tests/realtikvtest/statisticstest/...

bazel_txntest: failpoint-enable bazel_ci_prepare
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --remote_download_minimal --test_arg=-with-real-tikv \
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --test_arg=-with-real-tikv \
-- //tests/realtikvtest/txntest/...

bazel_addindextest: failpoint-enable bazel_ci_prepare
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --remote_download_minimal --test_arg=-with-real-tikv \
bazel $(BAZEL_GLOBAL_CONFIG) test $(BAZEL_CMD_CONFIG) --test_arg=-with-real-tikv \
-- //tests/realtikvtest/addindextest/...

bazel_lint: bazel_prepare
Expand Down
6 changes: 5 additions & 1 deletion bindinfo/bind_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ const (
Evolve = "evolve"
// Builtin indicates the binding is a builtin record for internal locking purpose. It is also the status for the builtin binding.
Builtin = "builtin"
// History indicate the binding is created from statement summary by plan digest
History = "history"
)

// Binding stores the basic bind hint info.
Expand All @@ -71,7 +73,9 @@ type Binding struct {
// Hint is the parsed hints, it is used to bind hints to stmt node.
Hint *hint.HintsSet `json:"-"`
// ID is the string form of Hint. It would be non-empty only when the status is `Using` or `PendingVerify`.
ID string `json:"-"`
ID string `json:"-"`
SQLDigest string
PlanDigest string
}

func (b *Binding) isSame(rb *Binding) bool {
Expand Down
63 changes: 63 additions & 0 deletions bindinfo/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"github.com/pingcap/tidb/parser/terror"
"github.com/pingcap/tidb/testkit"
"github.com/pingcap/tidb/util"
utilparser "github.com/pingcap/tidb/util/parser"
"github.com/pingcap/tidb/util/stmtsummary"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -1241,3 +1243,64 @@ func TestGCBindRecord(t *testing.T) {
tk.MustQuery("show global bindings").Check(testkit.Rows())
tk.MustQuery("select status from mysql.bind_info where original_sql = 'select * from `test` . `t` where `a` = ?'").Check(testkit.Rows())
}

func TestBindSQLDigest(t *testing.T) {
store, dom := testkit.CreateMockStoreAndDomain(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(pk int primary key, a int, b int, key(a), key(b))")

cases := []struct {
origin string
hint string
}{
// agg hints
{"select count(1) from t", "select /*+ hash_agg() */ count(1) from t"},
{"select count(1) from t", "select /*+ stream_agg() */ count(1) from t"},
// join hints
{"select * from t t1, t t2 where t1.a=t2.a", "select /*+ merge_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a"},
{"select * from t t1, t t2 where t1.a=t2.a", "select /*+ tidb_smj(t1, t2) */ * from t t1, t t2 where t1.a=t2.a"},
{"select * from t t1, t t2 where t1.a=t2.a", "select /*+ hash_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a"},
{"select * from t t1, t t2 where t1.a=t2.a", "select /*+ tidb_hj(t1, t2) */ * from t t1, t t2 where t1.a=t2.a"},
{"select * from t t1, t t2 where t1.a=t2.a", "select /*+ inl_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a"},
{"select * from t t1, t t2 where t1.a=t2.a", "select /*+ tidb_inlj(t1, t2) */ * from t t1, t t2 where t1.a=t2.a"},
{"select * from t t1, t t2 where t1.a=t2.a", "select /*+ inl_hash_join(t1, t2) */ * from t t1, t t2 where t1.a=t2.a"},
// index hints
{"select * from t", "select * from t use index(primary)"},
{"select * from t", "select /*+ use_index(primary) */ * from t"},
{"select * from t", "select * from t use index(a)"},
{"select * from t", "select /*+ use_index(a) */ * from t use index(a)"},
{"select * from t", "select * from t use index(b)"},
{"select * from t", "select /*+ use_index(b) */ * from t use index(b)"},
{"select a, b from t where a=1 or b=1", "select /*+ use_index_merge(t, a, b) */ a, b from t where a=1 or b=1"},
{"select * from t where a=1", "select /*+ ignore_index(t, a) */ * from t where a=1"},
// push-down hints
{"select * from t limit 10", "select /*+ limit_to_cop() */ * from t limit 10"},
{"select a, count(*) from t group by a", "select /*+ agg_to_cop() */ a, count(*) from t group by a"},
// index-merge hints
{"select a, b from t where a>1 or b>1", "select /*+ no_index_merge() */ a, b from t where a>1 or b>1"},
{"select a, b from t where a>1 or b>1", "select /*+ use_index_merge(t, a, b) */ a, b from t where a>1 or b>1"},
// runtime hints
{"select * from t", "select /*+ memory_quota(1024 MB) */ * from t"},
{"select * from t", "select /*+ max_execution_time(1000) */ * from t"},
// storage hints
{"select * from t", "select /*+ read_from_storage(tikv[t]) */ * from t"},
// others
{"select t1.a, t1.b from t t1 where t1.a in (select t2.a from t t2)", "select /*+ use_toja(true) */ t1.a, t1.b from t t1 where t1.a in (select t2.a from t t2)"},
}
for _, c := range cases {
stmtsummary.StmtSummaryByDigestMap.Clear()
utilCleanBindingEnv(tk, dom)
sql := "create global binding for " + c.origin + " using " + c.hint
tk.MustExec(sql)
res := tk.MustQuery(`show global bindings`).Rows()
require.Equal(t, len(res[0]), 11)

parser4binding := parser.New()
originNode, err := parser4binding.ParseOneStmt(c.origin, "utf8mb4", "utf8mb4_general_ci")
require.NoError(t, err)
_, sqlDigestWithDB := parser.NormalizeDigest(utilparser.RestoreWithDefaultDB(originNode, "test", c.origin))
require.Equal(t, res[0][9], sqlDigestWithDB.String())
}
}
10 changes: 9 additions & 1 deletion bindinfo/capture_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import (
"github.com/pingcap/tidb/bindinfo"
"github.com/pingcap/tidb/config"
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/parser"
"github.com/pingcap/tidb/parser/auth"
"github.com/pingcap/tidb/parser/model"
"github.com/pingcap/tidb/testkit"
utilparser "github.com/pingcap/tidb/util/parser"
"github.com/pingcap/tidb/util/stmtsummary"
"github.com/stretchr/testify/require"
"go.opencensus.io/stats/view"
Expand Down Expand Up @@ -397,7 +399,7 @@ func TestConcurrentCapture(t *testing.T) {
// Simulate an existing binding generated by concurrent CREATE BINDING, which has not been synchronized to current tidb-server yet.
// Actually, it is more common to be generated by concurrent baseline capture, I use Manual just for simpler test verification.
tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t`', 'select * from `test` . `t`', '', 'enabled', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" +
bindinfo.Manual + "')")
bindinfo.Manual + "', '', '')")
tk.MustQuery("select original_sql, source from mysql.bind_info where source != 'builtin'").Check(testkit.Rows(
"select * from `test` . `t` manual",
))
Expand Down Expand Up @@ -1011,5 +1013,11 @@ func TestCaptureHints(t *testing.T) {
res := tk.MustQuery(`show global bindings`).Rows()
require.Equal(t, len(res), 1) // this query is captured, and
require.True(t, strings.Contains(res[0][1].(string), capCase.hint)) // the binding contains the expected hint
// test sql digest
parser4binding := parser.New()
originNode, err := parser4binding.ParseOneStmt(capCase.query, "utf8mb4", "utf8mb4_general_ci")
require.NoError(t, err)
_, sqlDigestWithDB := parser.NormalizeDigest(utilparser.RestoreWithDefaultDB(originNode, "test", capCase.query))
require.Equal(t, res[0][9], sqlDigestWithDB.String())
}
}
23 changes: 20 additions & 3 deletions bindinfo/handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func (h *BindHandle) Update(fullLoad bool) (err error) {
ctx := kv.WithInternalSourceType(context.Background(), kv.InternalTxnBindInfo)
// No need to acquire the session context lock for ExecRestrictedSQL, it
// uses another background session.
rows, _, err := exec.ExecRestrictedSQL(ctx, nil, `SELECT original_sql, bind_sql, default_db, status, create_time, update_time, charset, collation, source
rows, _, err := exec.ExecRestrictedSQL(ctx, nil, `SELECT original_sql, bind_sql, default_db, status, create_time, update_time, charset, collation, source, sql_digest, plan_digest
FROM mysql.bind_info WHERE update_time > %? ORDER BY update_time, create_time`, updateTime)

if err != nil {
Expand Down Expand Up @@ -261,7 +261,7 @@ func (h *BindHandle) CreateBindRecord(sctx sessionctx.Context, record *BindRecor
record.Bindings[i].UpdateTime = now

// Insert the BindRecord to the storage.
_, err = exec.ExecuteInternal(ctx, `INSERT INTO mysql.bind_info VALUES (%?,%?, %?, %?, %?, %?, %?, %?, %?)`,
_, err = exec.ExecuteInternal(ctx, `INSERT INTO mysql.bind_info VALUES (%?,%?, %?, %?, %?, %?, %?, %?, %?, %?, %?)`,
record.OriginalSQL,
record.Bindings[i].BindSQL,
record.Db,
Expand All @@ -271,6 +271,8 @@ func (h *BindHandle) CreateBindRecord(sctx sessionctx.Context, record *BindRecor
record.Bindings[i].Charset,
record.Bindings[i].Collation,
record.Bindings[i].Source,
record.Bindings[i].SQLDigest,
record.Bindings[i].PlanDigest,
)
if err != nil {
return err
Expand Down Expand Up @@ -349,8 +351,18 @@ func (h *BindHandle) AddBindRecord(sctx sessionctx.Context, record *BindRecord)
}
record.Bindings[i].UpdateTime = now

if record.Bindings[i].SQLDigest == "" {
parser4binding := parser.New()
var originNode ast.StmtNode
originNode, err = parser4binding.ParseOneStmt(record.OriginalSQL, record.Bindings[i].Charset, record.Bindings[i].Collation)
if err != nil {
return err
}
_, sqlDigestWithDB := parser.NormalizeDigest(utilparser.RestoreWithDefaultDB(originNode, record.Db, record.OriginalSQL))
record.Bindings[i].SQLDigest = sqlDigestWithDB.String()
}
// Insert the BindRecord to the storage.
_, err = exec.ExecuteInternal(ctx, `INSERT INTO mysql.bind_info VALUES (%?, %?, %?, %?, %?, %?, %?, %?, %?)`,
_, err = exec.ExecuteInternal(ctx, `INSERT INTO mysql.bind_info VALUES (%?, %?, %?, %?, %?, %?, %?, %?, %?, %?, %?)`,
record.OriginalSQL,
record.Bindings[i].BindSQL,
record.Db,
Expand All @@ -360,6 +372,8 @@ func (h *BindHandle) AddBindRecord(sctx sessionctx.Context, record *BindRecord)
record.Bindings[i].Charset,
record.Bindings[i].Collation,
record.Bindings[i].Source,
record.Bindings[i].SQLDigest,
record.Bindings[i].PlanDigest,
)
if err != nil {
return err
Expand Down Expand Up @@ -680,6 +694,8 @@ func (h *BindHandle) newBindRecord(row chunk.Row) (string, *BindRecord, error) {
Charset: row.GetString(6),
Collation: row.GetString(7),
Source: row.GetString(8),
SQLDigest: row.GetString(9),
PlanDigest: row.GetString(10),
}
bindRecord := &BindRecord{
OriginalSQL: row.GetString(0),
Expand Down Expand Up @@ -900,6 +916,7 @@ func (h *BindHandle) CaptureBaselines() {
Charset: charset,
Collation: collation,
Source: Capture,
SQLDigest: digest.String(),
}
// We don't need to pass the `sctx` because the BindSQL has been validated already.
err = h.CreateBindRecord(nil, &BindRecord{OriginalSQL: normalizedSQL, Db: dbName, Bindings: []Binding{binding}})
Expand Down
19 changes: 11 additions & 8 deletions bindinfo/handle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func TestBindingLastUpdateTimeWithInvalidBind(t *testing.T) {
require.Equal(t, updateTime0, "0000-00-00 00:00:00")

tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t`', 'select * from `test` . `t` use index(`idx`)', 'test', 'enabled', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" +
bindinfo.Manual + "')")
bindinfo.Manual + "', '', '')")
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int)")
Expand Down Expand Up @@ -137,8 +137,9 @@ func TestBindParse(t *testing.T) {
charset := "utf8mb4"
collation := "utf8mb4_bin"
source := bindinfo.Manual
sql := fmt.Sprintf(`INSERT INTO mysql.bind_info(original_sql,bind_sql,default_db,status,create_time,update_time,charset,collation,source) VALUES ('%s', '%s', '%s', '%s', NOW(), NOW(),'%s', '%s', '%s')`,
originSQL, bindSQL, defaultDb, status, charset, collation, source)
mockDigest := "0f644e22c38ecc71d4592c52df127df7f86b6ca7f7c0ee899113b794578f9396"
sql := fmt.Sprintf(`INSERT INTO mysql.bind_info(original_sql,bind_sql,default_db,status,create_time,update_time,charset,collation,source, sql_digest, plan_digest) VALUES ('%s', '%s', '%s', '%s', NOW(), NOW(),'%s', '%s', '%s', '%s', '%s')`,
originSQL, bindSQL, defaultDb, status, charset, collation, source, mockDigest, mockDigest)
tk.MustExec(sql)
bindHandle := bindinfo.NewBindHandle(tk.Session())
err := bindHandle.Update(true)
Expand Down Expand Up @@ -221,7 +222,7 @@ func TestEvolveInvalidBindings(t *testing.T) {
tk.MustExec("create global binding for select * from t where a > 10 using select /*+ USE_INDEX(t) */ * from t where a > 10")
// Manufacture a rejected binding by hacking mysql.bind_info.
tk.MustExec("insert into mysql.bind_info values('select * from test . t where a > ?', 'SELECT /*+ USE_INDEX(t,idx_a) */ * FROM test.t WHERE a > 10', 'test', 'rejected', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" +
bindinfo.Manual + "')")
bindinfo.Manual + "', '', '')")
tk.MustQuery("select bind_sql, status from mysql.bind_info where source != 'builtin'").Sort().Check(testkit.Rows(
"SELECT /*+ USE_INDEX(`t` )*/ * FROM `test`.`t` WHERE `a` > 10 enabled",
"SELECT /*+ USE_INDEX(t,idx_a) */ * FROM test.t WHERE a > 10 rejected",
Expand All @@ -242,6 +243,8 @@ func TestEvolveInvalidBindings(t *testing.T) {
require.Equal(t, "SELECT /*+ USE_INDEX(t,idx_a) */ * FROM test.t WHERE a > 10", rows[1][1])
status = rows[1][3].(string)
require.True(t, status == bindinfo.Enabled || status == bindinfo.Rejected)
_, sqlDigestWithDB := parser.NormalizeDigest("select * from test.t where a > 10") // test sqlDigest if exists after add columns to mysql.bind_info
require.Equal(t, rows[0][9], sqlDigestWithDB.String())
}

func TestSetBindingStatus(t *testing.T) {
Expand Down Expand Up @@ -319,9 +322,9 @@ func TestSetBindingStatusWithoutBindingInCache(t *testing.T) {

// Simulate creating bindings on other machines
tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t` where `a` > ?', 'SELECT /*+ USE_INDEX(`t` `idx_a`)*/ * FROM `test`.`t` WHERE `a` > 10', 'test', 'deleted', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" +
bindinfo.Manual + "')")
bindinfo.Manual + "', '', '')")
tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t` where `a` > ?', 'SELECT /*+ USE_INDEX(`t` `idx_a`)*/ * FROM `test`.`t` WHERE `a` > 10', 'test', 'enabled', '2000-01-02 09:00:00', '2000-01-02 09:00:00', '', '','" +
bindinfo.Manual + "')")
bindinfo.Manual + "', '', '')")
dom.BindHandle().Clear()
tk.MustExec("set binding disabled for select * from t where a > 10")
tk.MustExec("admin reload bindings")
Expand All @@ -334,9 +337,9 @@ func TestSetBindingStatusWithoutBindingInCache(t *testing.T) {

// Simulate creating bindings on other machines
tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t` where `a` > ?', 'SELECT * FROM `test`.`t` WHERE `a` > 10', 'test', 'deleted', '2000-01-01 09:00:00', '2000-01-01 09:00:00', '', '','" +
bindinfo.Manual + "')")
bindinfo.Manual + "', '', '')")
tk.MustExec("insert into mysql.bind_info values('select * from `test` . `t` where `a` > ?', 'SELECT * FROM `test`.`t` WHERE `a` > 10', 'test', 'disabled', '2000-01-02 09:00:00', '2000-01-02 09:00:00', '', '','" +
bindinfo.Manual + "')")
bindinfo.Manual + "', '', '')")
dom.BindHandle().Clear()
tk.MustExec("set binding enabled for select * from t where a > 10")
tk.MustExec("admin reload bindings")
Expand Down
Loading

0 comments on commit 8bda001

Please sign in to comment.