From 87999d1d4ac60b0242701418c809ee6177e93ed5 Mon Sep 17 00:00:00 2001 From: Yuanjia Zhang Date: Wed, 29 May 2024 17:23:51 +0800 Subject: [PATCH] planner: fix small regression caused by #53094 (#53646) ref pingcap/tidb#50618 --- pkg/planner/core/plan_cache.go | 39 ++++++++++++++++------------ pkg/planner/core/plan_cache_lru.go | 4 +++ pkg/planner/core/plan_cache_utils.go | 4 +-- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/pkg/planner/core/plan_cache.go b/pkg/planner/core/plan_cache.go index c2ca1ff8d250b..6ad798d3f80e3 100644 --- a/pkg/planner/core/plan_cache.go +++ b/pkg/planner/core/plan_cache.go @@ -215,32 +215,39 @@ func GetPlanFromSessionPlanCache(ctx context.Context, sctx sessionctx.Context, } } - matchOpts, err := GetMatchOpts(sctx, is, stmt, params) - if err != nil { - return nil, nil, err - } + var matchOpts *utilpc.PlanCacheMatchOpts if stmtCtx.UseCache() { - if plan, names, ok, err := getCachedPlan(sctx, isNonPrepared, cacheKey, bindSQL, is, stmt, matchOpts); err != nil || ok { - return plan, names, err + var cacheVal kvcache.Value + var hit, isPointPlan bool + if stmt.PointGet.Executor != nil { // if it's PointGet Plan, no need to use MatchOpts + cacheVal, hit = sctx.GetSessionPlanCache().Get(cacheKey, nil) + isPointPlan = true + } else { + matchOpts = GetMatchOpts(sctx, is, stmt, params) + cacheVal, hit = sctx.GetSessionPlanCache().Get(cacheKey, matchOpts) + } + if hit { + if plan, names, ok, err := adjustCachedPlan(sctx, cacheVal.(*PlanCacheValue), isNonPrepared, isPointPlan, cacheKey, bindSQL, is, stmt); err != nil || ok { + return plan, names, err + } } } + if matchOpts == nil { + matchOpts = GetMatchOpts(sctx, is, stmt, params) + } return generateNewPlan(ctx, sctx, isNonPrepared, is, stmt, cacheKey, latestSchemaVersion, bindSQL, matchOpts) } -func getCachedPlan(sctx sessionctx.Context, isNonPrepared bool, cacheKey kvcache.Key, bindSQL string, - is infoschema.InfoSchema, stmt *PlanCacheStmt, matchOpts *utilpc.PlanCacheMatchOpts) (base.Plan, +func adjustCachedPlan(sctx sessionctx.Context, cachedVal *PlanCacheValue, isNonPrepared, isPointPlan bool, + cacheKey kvcache.Key, bindSQL string, is infoschema.InfoSchema, stmt *PlanCacheStmt) (base.Plan, []*types.FieldName, bool, error) { sessVars := sctx.GetSessionVars() stmtCtx := sessVars.StmtCtx - - candidate, exist := sctx.GetSessionPlanCache().Get(cacheKey, matchOpts) - if !exist { - return nil, nil, false, nil - } - cachedVal := candidate.(*PlanCacheValue) - if err := checkPreparedPriv(sctx, stmt, is); err != nil { - return nil, nil, false, err + if !isPointPlan { // keep the prior behavior + if err := checkPreparedPriv(sctx, stmt, is); err != nil { + return nil, nil, false, err + } } for tblInfo, unionScan := range cachedVal.TblInfo2UnionScan { if !unionScan && tableHasDirtyContent(sctx.GetPlanCtx(), tblInfo) { diff --git a/pkg/planner/core/plan_cache_lru.go b/pkg/planner/core/plan_cache_lru.go index ce74307738e29..6be81eac0246e 100644 --- a/pkg/planner/core/plan_cache_lru.go +++ b/pkg/planner/core/plan_cache_lru.go @@ -253,6 +253,10 @@ func (l *LRUPlanCache) memoryControl() { // PickPlanFromBucket pick one plan from bucket func (l *LRUPlanCache) pickFromBucket(bucket map[*list.Element]struct{}, matchOpts *utilpc.PlanCacheMatchOpts) (*list.Element, bool) { for k := range bucket { + if matchOpts == nil { // for PointGet Plan + return k, true + } + plan := k.Value.(*planCacheEntry).PlanValue.(*PlanCacheValue) // check param types' compatibility ok1 := checkTypesCompatibility4PC(plan.matchOpts.ParamTypes, matchOpts.ParamTypes) diff --git a/pkg/planner/core/plan_cache_utils.go b/pkg/planner/core/plan_cache_utils.go index 7909f35921787..c5833c11a89bb 100644 --- a/pkg/planner/core/plan_cache_utils.go +++ b/pkg/planner/core/plan_cache_utils.go @@ -559,7 +559,7 @@ func GetPreparedStmt(stmt *ast.ExecuteStmt, vars *variable.SessionVars) (*PlanCa // GetMatchOpts get options to fetch plan or generate new plan // we can add more options here -func GetMatchOpts(sctx sessionctx.Context, is infoschema.InfoSchema, stmt *PlanCacheStmt, params []expression.Expression) (*utilpc.PlanCacheMatchOpts, error) { +func GetMatchOpts(sctx sessionctx.Context, is infoschema.InfoSchema, stmt *PlanCacheStmt, params []expression.Expression) *utilpc.PlanCacheMatchOpts { var statsVerHash uint64 var limitOffsetAndCount []uint64 @@ -606,7 +606,7 @@ func GetMatchOpts(sctx sessionctx.Context, is infoschema.InfoSchema, stmt *PlanC StatsVersionHash: statsVerHash, ParamTypes: parseParamTypes(sctx, params), ForeignKeyChecks: sctx.GetSessionVars().ForeignKeyChecks, - }, nil + } } // CheckTypesCompatibility4PC compares FieldSlice with []*types.FieldType