Skip to content

Commit

Permalink
planner: ignore close-stmt to make more queries can hit plan cache (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
qw4990 authored Mar 15, 2022
1 parent 76f2437 commit 678397b
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 3 deletions.
4 changes: 3 additions & 1 deletion executor/prepared.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,9 @@ func (e *DeallocateExec) Next(ctx context.Context, req *chunk.Chunk) error {
if err != nil {
return err
}
e.ctx.PreparedPlanCache().Delete(cacheKey)
if !vars.IgnorePreparedCacheCloseStmt { // keep the plan in cache
e.ctx.PreparedPlanCache().Delete(cacheKey)
}
}
vars.RemovePreparedStmt(id)
return nil
Expand Down
9 changes: 9 additions & 0 deletions executor/set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,15 @@ func TestSetVar(t *testing.T) {
require.Error(t, tk.ExecToErr("select @@session.tidb_enable_column_tracking"))
require.Error(t, tk.ExecToErr("set tidb_enable_column_tracking = 0"))
require.Error(t, tk.ExecToErr("set global tidb_enable_column_tracking = -1"))

// test for tidb_ignore_prepared_cache_close_stmt
tk.MustQuery("select @@global.tidb_ignore_prepared_cache_close_stmt").Check(testkit.Rows("0")) // default value is 0
tk.MustExec("set global tidb_ignore_prepared_cache_close_stmt=1")
tk.MustQuery("select @@global.tidb_ignore_prepared_cache_close_stmt").Check(testkit.Rows("1"))
tk.MustQuery("show global variables like 'tidb_ignore_prepared_cache_close_stmt'").Check(testkit.Rows("tidb_ignore_prepared_cache_close_stmt ON"))
tk.MustExec("set global tidb_ignore_prepared_cache_close_stmt=0")
tk.MustQuery("select @@global.tidb_ignore_prepared_cache_close_stmt").Check(testkit.Rows("0"))
tk.MustQuery("show global variables like 'tidb_ignore_prepared_cache_close_stmt'").Check(testkit.Rows("tidb_ignore_prepared_cache_close_stmt OFF"))
}

func TestTruncateIncorrectIntSessionVar(t *testing.T) {
Expand Down
74 changes: 74 additions & 0 deletions planner/core/prepare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,80 @@ import (
"github.com/stretchr/testify/require"
)

func TestPreparePointGetWithDML(t *testing.T) {
store, clean := testkit.CreateMockStore(t)
defer clean()
orgEnable := core.PreparedPlanCacheEnabled()
defer core.SetPreparedPlanCache(orgEnable)
core.SetPreparedPlanCache(true)
se, err := session.CreateSession4TestWithOpt(store, &session.Opt{
PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64),
})
require.NoError(t, err)
tk := testkit.NewTestKitWithSession(t, store, se)

tk.MustExec(`use test`)
tk.MustExec(`drop table if exists t`)
tk.MustExec(`create table t(a int, unique key(a))`)
tk.MustExec(`insert into t values(1), (2)`)

// txn1 left a cached plan
tk.MustExec(`begin`)
tk.MustExec(`prepare stmt from 'update t set a = ? where a = ?'`)
tk.MustExec(`set @a=1`)
tk.MustExec(`execute stmt using @a, @a`)
tk.MustExec(`commit`)

// txn2 can reuse the cached plan generated by txn1 directly
tk.MustExec(`begin`)
tk.MustExec(`prepare stmt from 'update t set a = ? where a = ?'`)
tk.MustExec(`set @a=2`)
tk.MustExec(`execute stmt using @a, @a`) // can reuse the cached plan directly
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1"))
tk.MustExec(`rollback`)
}

func TestPrepareIgnoreCloseStmtCmd(t *testing.T) {
store, clean := testkit.CreateMockStore(t)
defer clean()
orgEnable := core.PreparedPlanCacheEnabled()
defer core.SetPreparedPlanCache(orgEnable)
core.SetPreparedPlanCache(true)
se, err := session.CreateSession4TestWithOpt(store, &session.Opt{
PreparedPlanCache: kvcache.NewSimpleLRUCache(100, 0.1, math.MaxUint64),
})
require.NoError(t, err)
tk := testkit.NewTestKitWithSession(t, store, se)

tk.MustExec(`use test`)
tk.MustExec(`drop table if exists t`)
tk.MustExec(`create table t(a int, unique key(a))`)

// disable the ignore-stmt-cmd
tk.MustExec(`set @@tidb_ignore_prepared_cache_close_stmt=0`)
tk.MustQuery(`select @@tidb_ignore_prepared_cache_close_stmt`).Check(testkit.Rows("0"))
tk.MustExec(`prepare stmt from 'select * from t'`)
tk.MustQuery(`execute stmt`).Check(testkit.Rows())
tk.MustQuery(`execute stmt`).Check(testkit.Rows())
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1"))
tk.MustExec(`deallocate prepare stmt`) // close/deallocate this stmt
tk.MustExec(`prepare stmt from 'select * from t'`)
tk.MustQuery(`execute stmt`).Check(testkit.Rows())
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("0")) // cannot reuse last plan since it is closed

// enable the ignore-stmt-cmd
tk.MustExec(`set tidb_ignore_prepared_cache_close_stmt=1`)
tk.MustQuery(`select @@tidb_ignore_prepared_cache_close_stmt`).Check(testkit.Rows("1"))
tk.MustExec(`prepare stmt from 'select * from t'`)
tk.MustQuery(`execute stmt`).Check(testkit.Rows())
tk.MustQuery(`execute stmt`).Check(testkit.Rows())
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1"))
tk.MustExec(`deallocate prepare stmt`) // close/deallocate this stmt
tk.MustExec(`prepare stmt from 'select * from t'`)
tk.MustQuery(`execute stmt`).Check(testkit.Rows())
tk.MustQuery(`select @@last_plan_from_cache`).Check(testkit.Rows("1")) // can reuse last plan since last close-cmd was ignored
}

func TestRandomFlushPlanCache(t *testing.T) {
store, clean := testkit.CreateMockStore(t)
defer clean()
Expand Down
4 changes: 3 additions & 1 deletion server/driver_tidb.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ func (ts *TiDBStatement) Close() error {
if err != nil {
return err
}
ts.ctx.PreparedPlanCache().Delete(cacheKey)
if !ts.ctx.GetSessionVars().IgnorePreparedCacheCloseStmt { // keep the plan in cache
ts.ctx.PreparedPlanCache().Delete(cacheKey)
}
}
ts.ctx.GetSessionVars().RemovePreparedStmt(ts.id)
}
Expand Down
4 changes: 3 additions & 1 deletion session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,9 @@ func (s *session) cleanRetryInfo() {
if i > 0 && preparedAst != nil {
plannercore.SetPstmtIDSchemaVersion(cacheKey, stmtText, preparedAst.SchemaVersion, s.sessionVars.IsolationReadEngines)
}
s.PreparedPlanCache().Delete(cacheKey)
if !s.sessionVars.IgnorePreparedCacheCloseStmt { // keep the plan in cache
s.PreparedPlanCache().Delete(cacheKey)
}
}
s.sessionVars.RemovePreparedStmt(stmtID)
}
Expand Down
2 changes: 2 additions & 0 deletions sessionctx/variable/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,8 @@ type SessionVars struct {
EnableMutationChecker bool
// AssertionLevel controls how strict the assertions on data mutations should be.
AssertionLevel AssertionLevel
// IgnorePreparedCacheCloseStmt controls if ignore the close-stmt command for prepared statement.
IgnorePreparedCacheCloseStmt bool
// BatchPendingTiFlashCount shows the threshold of pending TiFlash tables when batch adding.
BatchPendingTiFlashCount int
}
Expand Down
6 changes: 6 additions & 0 deletions sessionctx/variable/sysvar.go
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,12 @@ var defaultSysVars = []*SysVar{
}
return string(info), nil
}},
{Scope: ScopeGlobal | ScopeSession, Name: TiDBIgnorePreparedCacheCloseStmt, Value: BoolToOnOff(DefTiDBIgnorePreparedCacheCloseStmt), Type: TypeBool,
SetSession: func(vars *SessionVars, s string) error {
vars.IgnorePreparedCacheCloseStmt = TiDBOptOn(s)
return nil
},
},
}

// FeedbackProbability points to the FeedbackProbability in statistics package.
Expand Down
4 changes: 4 additions & 0 deletions sessionctx/variable/tidb_vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,9 @@ const (
// index inconsistency problems.
TiDBTxnAssertionLevel = "tidb_txn_assertion_level"

// TiDBIgnorePreparedCacheCloseStmt indicates whether to ignore close-stmt commands for prepared statements.
TiDBIgnorePreparedCacheCloseStmt = "tidb_ignore_prepared_cache_close_stmt"

// TiDBBatchPendingTiFlashCount indicates the maximum count of non-available TiFlash tables.
TiDBBatchPendingTiFlashCount = "tidb_batch_pending_tiflash_count"
)
Expand Down Expand Up @@ -800,6 +803,7 @@ const (
DefSysdateIsNow = false
DefTiDBEnableMutationChecker = false
DefTiDBTxnAssertionLevel = AssertionOffStr
DefTiDBIgnorePreparedCacheCloseStmt = false
DefTiDBBatchPendingTiFlashCount = 4000
)

Expand Down

0 comments on commit 678397b

Please sign in to comment.