Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

planner: refactor plan-cache UseCache flag #40256

Merged
merged 12 commits into from
Jan 3, 2023
16 changes: 8 additions & 8 deletions executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3621,10 +3621,10 @@ func TestPointGetPreparedPlan(t *testing.T) {

pspk1Id, _, _, err := tk.Session().PrepareStmt("select * from t where a = ?")
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[pspk1Id].(*plannercore.PlanCacheStmt).PreparedAst.UseCache = false
tk.Session().GetSessionVars().PreparedStmts[pspk1Id].(*plannercore.PlanCacheStmt).StmtCacheable = false
pspk2Id, _, _, err := tk.Session().PrepareStmt("select * from t where ? = a ")
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[pspk2Id].(*plannercore.PlanCacheStmt).PreparedAst.UseCache = false
tk.Session().GetSessionVars().PreparedStmts[pspk2Id].(*plannercore.PlanCacheStmt).StmtCacheable = false

ctx := context.Background()
// first time plan generated
Expand Down Expand Up @@ -3664,7 +3664,7 @@ func TestPointGetPreparedPlan(t *testing.T) {
// unique index
psuk1Id, _, _, err := tk.Session().PrepareStmt("select * from t where b = ? ")
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[psuk1Id].(*plannercore.PlanCacheStmt).PreparedAst.UseCache = false
tk.Session().GetSessionVars().PreparedStmts[psuk1Id].(*plannercore.PlanCacheStmt).StmtCacheable = false

rs, err = tk.Session().ExecutePreparedStmt(ctx, psuk1Id, expression.Args2Expressions4Test(1))
require.NoError(t, err)
Expand Down Expand Up @@ -3782,7 +3782,7 @@ func TestPointGetPreparedPlanWithCommitMode(t *testing.T) {

pspk1Id, _, _, err := tk1.Session().PrepareStmt("select * from t where a = ?")
require.NoError(t, err)
tk1.Session().GetSessionVars().PreparedStmts[pspk1Id].(*plannercore.PlanCacheStmt).PreparedAst.UseCache = false
tk1.Session().GetSessionVars().PreparedStmts[pspk1Id].(*plannercore.PlanCacheStmt).StmtCacheable = false

ctx := context.Background()
// first time plan generated
Expand Down Expand Up @@ -3848,11 +3848,11 @@ func TestPointUpdatePreparedPlan(t *testing.T) {

updateID1, pc, _, err := tk.Session().PrepareStmt(`update t set c = c + 1 where a = ?`)
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[updateID1].(*plannercore.PlanCacheStmt).PreparedAst.UseCache = false
tk.Session().GetSessionVars().PreparedStmts[updateID1].(*plannercore.PlanCacheStmt).StmtCacheable = false
require.Equal(t, 1, pc)
updateID2, pc, _, err := tk.Session().PrepareStmt(`update t set c = c + 2 where ? = a`)
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[updateID2].(*plannercore.PlanCacheStmt).PreparedAst.UseCache = false
tk.Session().GetSessionVars().PreparedStmts[updateID2].(*plannercore.PlanCacheStmt).StmtCacheable = false
require.Equal(t, 1, pc)

ctx := context.Background()
Expand Down Expand Up @@ -3887,7 +3887,7 @@ func TestPointUpdatePreparedPlan(t *testing.T) {
// unique index
updUkID1, _, _, err := tk.Session().PrepareStmt(`update t set c = c + 10 where b = ?`)
require.NoError(t, err)
tk.Session().GetSessionVars().PreparedStmts[updUkID1].(*plannercore.PlanCacheStmt).PreparedAst.UseCache = false
tk.Session().GetSessionVars().PreparedStmts[updUkID1].(*plannercore.PlanCacheStmt).StmtCacheable = false
rs, err = tk.Session().ExecutePreparedStmt(ctx, updUkID1, expression.Args2Expressions4Test(3))
require.Nil(t, rs)
require.NoError(t, err)
Expand Down Expand Up @@ -3956,7 +3956,7 @@ func TestPointUpdatePreparedPlanWithCommitMode(t *testing.T) {

ctx := context.Background()
updateID1, _, _, err := tk1.Session().PrepareStmt(`update t set c = c + 1 where a = ?`)
tk1.Session().GetSessionVars().PreparedStmts[updateID1].(*plannercore.PlanCacheStmt).PreparedAst.UseCache = false
tk1.Session().GetSessionVars().PreparedStmts[updateID1].(*plannercore.PlanCacheStmt).StmtCacheable = false
require.NoError(t, err)

// first time plan generated
Expand Down
1 change: 0 additions & 1 deletion parser/ast/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,6 @@ type Prepared struct {
StmtType string
Params []ParamMarkerExpr
SchemaVersion int64
UseCache bool
CachedPlan interface{}
CachedNames interface{}
}
Expand Down
13 changes: 8 additions & 5 deletions planner/core/plan_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func planCachePreprocess(ctx context.Context, sctx sessionctx.Context, isNonPrep
// So we need to clear the current session's plan cache.
// And update lastUpdateTime to the newest one.
expiredTimeStamp4PC := domain.GetDomain(sctx).ExpiredTimeStamp4PC()
if stmtAst.UseCache && expiredTimeStamp4PC.Compare(vars.LastUpdateTime4PC) > 0 {
if stmt.StmtCacheable && expiredTimeStamp4PC.Compare(vars.LastUpdateTime4PC) > 0 {
sctx.GetPlanCache(isNonPrepared).DeleteAll()
stmtAst.CachedPlan = nil
vars.LastUpdateTime4PC = expiredTimeStamp4PC
Expand All @@ -127,7 +127,10 @@ func GetPlanFromSessionPlanCache(ctx context.Context, sctx sessionctx.Context,
sessVars := sctx.GetSessionVars()
stmtCtx := sessVars.StmtCtx
stmtAst := stmt.PreparedAst
stmtCtx.UseCache = stmtAst.UseCache
stmtCtx.UseCache = stmt.StmtCacheable
if !stmt.StmtCacheable {
stmtCtx.SetSkipPlanCache(errors.Errorf("skip plan-cache: %s", stmt.UncacheableReason))
}

var bindSQL string
var ignorePlanCache = false
Expand All @@ -136,7 +139,7 @@ func GetPlanFromSessionPlanCache(ctx context.Context, sctx sessionctx.Context,
// rebuild the plan. So we set this value in rc or for update read. In other cases, let it be 0.
var latestSchemaVersion int64

if stmtAst.UseCache {
if stmtCtx.UseCache {
bindSQL, ignorePlanCache = GetBindSQL4PlanCache(sctx, stmt)
if sctx.GetSessionVars().IsIsolation(ast.ReadCommitted) || stmt.ForUpdateRead {
// In Rc or ForUpdateRead, we should check if the information schema has been changed since
Expand All @@ -152,13 +155,13 @@ func GetPlanFromSessionPlanCache(ctx context.Context, sctx sessionctx.Context,

paramNum, paramTypes := parseParamTypes(sctx, params)

if stmtAst.UseCache && stmtAst.CachedPlan != nil && !ignorePlanCache { // for point query plan
if stmtCtx.UseCache && stmtAst.CachedPlan != nil && !ignorePlanCache { // for point query plan
if plan, names, ok, err := getCachedPointPlan(stmtAst, sessVars, stmtCtx); ok {
return plan, names, err
}
}

if stmtAst.UseCache && !ignorePlanCache { // for non-point plans
if stmtCtx.UseCache && !ignorePlanCache { // for non-point plans
if plan, names, ok, err := getCachedPlan(sctx, isNonPrepared, cacheKey, bindSQL, is, stmt,
paramTypes); err != nil || ok {
return plan, names, err
Expand Down
16 changes: 16 additions & 0 deletions planner/core/plan_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,3 +384,19 @@ func TestPlanCacheDiagInfo(t *testing.T) {
tk.MustExec("execute stmt using @a, @b") // a=1 and a=1 -> a=1
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip plan-cache: some parameters may be overwritten"))
}

func TestUncacheableReason(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t (a int)")

tk.MustExec("prepare st from 'select * from t limit ?'")
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip plan-cache: query has 'limit ?' is un-cacheable"))

tk.MustExec("set @a=1")
tk.MustQuery("execute st using @a").Check(testkit.Rows())
tk.MustExec("prepare st from 'select * from t limit ?'")
// show the corresponding un-cacheable reason at execute-stage as well
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1105 skip plan-cache: query has 'limit ?' is un-cacheable"))
}
16 changes: 12 additions & 4 deletions planner/core/plan_cache_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,12 +119,14 @@ func GeneratePlanCacheStmtWithAST(ctx context.Context, sctx sessionctx.Context,
var (
normalizedSQL4PC, digest4PC string
selectStmtNode ast.StmtNode
cacheable bool
reason string
)
if !vars.EnablePreparedPlanCache {
prepared.UseCache = false
cacheable = false
reason = "plan cache is disabled"
} else {
cacheable, reason := CacheableWithCtx(sctx, paramStmt, ret.InfoSchema)
prepared.UseCache = cacheable
cacheable, reason = CacheableWithCtx(sctx, paramStmt, ret.InfoSchema)
if !cacheable {
sctx.GetSessionVars().StmtCtx.AppendWarning(errors.Errorf("skip plan-cache: " + reason))
}
Expand Down Expand Up @@ -160,6 +162,8 @@ func GeneratePlanCacheStmtWithAST(ctx context.Context, sctx sessionctx.Context,
SnapshotTSEvaluator: ret.SnapshotTSEvaluator,
NormalizedSQL4PC: normalizedSQL4PC,
SQLDigest4PC: digest4PC,
StmtCacheable: cacheable,
UncacheableReason: reason,
}
if err = CheckPreparedPriv(sctx, preparedObj, ret.InfoSchema); err != nil {
return nil, nil, 0, err
Expand Down Expand Up @@ -412,7 +416,11 @@ type PlanCacheStmt struct {
// Executor is only used for point get scene.
// Notice that we should only cache the PointGetExecutor that have a snapshot with MaxTS in it.
// If the current plan is not PointGet or does not use MaxTS optimization, this value should be nil here.
Executor interface{}
Executor interface{}

StmtCacheable bool // Whether this stmt is cacheable.
UncacheableReason string // Why this stmt is uncacheable.

NormalizedSQL string
NormalizedPlan string
SQLDigest *parser.Digest
Expand Down
2 changes: 1 addition & 1 deletion planner/core/prepare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func TestPointGetPreparedPlan4PlanCache(t *testing.T) {

pspk1Id, _, _, err := tk1.Session().PrepareStmt("select * from t where a = ?")
require.NoError(t, err)
tk1.Session().GetSessionVars().PreparedStmts[pspk1Id].(*core.PlanCacheStmt).PreparedAst.UseCache = false
tk1.Session().GetSessionVars().PreparedStmts[pspk1Id].(*core.PlanCacheStmt).StmtCacheable = false

ctx := context.Background()
// first time plan generated
Expand Down