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 LRU code (#41618) #41648

Open
wants to merge 1 commit into
base: release-6.5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions planner/core/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ go_library(
"//util/mock",
"//util/paging",
"//util/parser",
"//util/plancache",
"//util/plancodec",
"//util/ranger",
"//util/rowcodec",
Expand Down Expand Up @@ -261,6 +262,7 @@ go_test(
"//util/kvcache",
"//util/logutil",
"//util/mock",
"//util/plancache",
"//util/plancodec",
"//util/ranger",
"//util/set",
Expand Down
51 changes: 51 additions & 0 deletions planner/core/plan_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
"github.com/pingcap/tidb/util/collate"
"github.com/pingcap/tidb/util/kvcache"
"github.com/pingcap/tidb/util/logutil"
utilpc "github.com/pingcap/tidb/util/plancache"
"github.com/pingcap/tidb/util/ranger"
"go.uber.org/zap"
)
Expand Down Expand Up @@ -151,14 +152,30 @@ func GetPlanFromSessionPlanCache(ctx context.Context, sctx sessionctx.Context,
}
}

<<<<<<< HEAD
paramTypes := parseParamTypes(sctx, params)

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

matchOpts, err := GetMatchOpts(sctx, stmt.PreparedAst.Stmt, params)
if err != nil {
return nil, nil, err
}
if stmtCtx.UseCache { // for non-point plans
if plan, names, ok, err := getCachedPlan(sctx, isNonPrepared, cacheKey, bindSQL, is, stmt, matchOpts); err != nil || ok {
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
return plan, names, err
}
}

<<<<<<< HEAD
if stmtCtx.UseCache { // for non-point plans
if plan, names, ok, err := getGeneralPlan(sctx, isGeneralPlanCache, cacheKey, bindSQL, is, stmt,
paramTypes); err != nil || ok {
Expand All @@ -167,6 +184,9 @@ func GetPlanFromSessionPlanCache(ctx context.Context, sctx sessionctx.Context,
}

return generateNewPlan(ctx, sctx, isGeneralPlanCache, is, stmt, cacheKey, latestSchemaVersion, paramTypes, bindSQL)
=======
return generateNewPlan(ctx, sctx, isNonPrepared, is, stmt, cacheKey, latestSchemaVersion, bindSQL, matchOpts)
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
}

// parseParamTypes get parameters' types in PREPARE statement
Expand Down Expand Up @@ -212,13 +232,22 @@ func getPointQueryPlan(stmt *ast.Prepared, sessVars *variable.SessionVars, stmtC
return plan, names, true, nil
}

<<<<<<< HEAD
func getGeneralPlan(sctx sessionctx.Context, isGeneralPlanCache bool, cacheKey kvcache.Key, bindSQL string,
is infoschema.InfoSchema, stmt *PlanCacheStmt, paramTypes []*types.FieldType) (Plan,
=======
func getCachedPlan(sctx sessionctx.Context, isNonPrepared bool, cacheKey kvcache.Key, bindSQL string,
is infoschema.InfoSchema, stmt *PlanCacheStmt, matchOpts *utilpc.PlanCacheMatchOpts) (Plan,
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
[]*types.FieldName, bool, error) {
sessVars := sctx.GetSessionVars()
stmtCtx := sessVars.StmtCtx

<<<<<<< HEAD
candidate, exist := sctx.GetPlanCache(isGeneralPlanCache).Get(cacheKey, paramTypes)
=======
candidate, exist := sctx.GetPlanCache(isNonPrepared).Get(cacheKey, matchOpts)
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
if !exist {
return nil, nil, false, nil
}
Expand Down Expand Up @@ -256,9 +285,15 @@ func getGeneralPlan(sctx sessionctx.Context, isGeneralPlanCache bool, cacheKey k

// generateNewPlan call the optimizer to generate a new plan for current statement
// and try to add it to cache
<<<<<<< HEAD
func generateNewPlan(ctx context.Context, sctx sessionctx.Context, isGeneralPlanCache bool, is infoschema.InfoSchema,
stmt *PlanCacheStmt, cacheKey kvcache.Key, latestSchemaVersion int64, paramTypes []*types.FieldType,
bindSQL string) (Plan, []*types.FieldName, error) {
=======
func generateNewPlan(ctx context.Context, sctx sessionctx.Context, isNonPrepared bool, is infoschema.InfoSchema,
stmt *PlanCacheStmt, cacheKey kvcache.Key, latestSchemaVersion int64, bindSQL string,
matchOpts *utilpc.PlanCacheMatchOpts) (Plan, []*types.FieldName, error) {
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
stmtAst := stmt.PreparedAst
sessVars := sctx.GetSessionVars()
stmtCtx := sessVars.StmtCtx
Expand All @@ -276,7 +311,15 @@ func generateNewPlan(ctx context.Context, sctx sessionctx.Context, isGeneralPlan
}

// check whether this plan is cacheable.
<<<<<<< HEAD
checkPlanCacheability(sctx, p, len(paramTypes))
=======
if stmtCtx.UseCache {
if cacheable, reason := isPlanCacheable(sctx, p, len(matchOpts.ParamTypes), len(matchOpts.LimitOffsetAndCount)); !cacheable {
stmtCtx.SetSkipPlanCache(errors.Errorf(reason))
}
}
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))

// put this plan into the plan cache.
if stmtCtx.UseCache {
Expand All @@ -289,11 +332,19 @@ func generateNewPlan(ctx context.Context, sctx sessionctx.Context, isGeneralPlan
}
sessVars.IsolationReadEngines[kv.TiFlash] = struct{}{}
}
<<<<<<< HEAD
cached := NewPlanCacheValue(p, names, stmtCtx.TblInfo2UnionScan, paramTypes)
stmt.NormalizedPlan, stmt.PlanDigest = NormalizePlan(p)
stmtCtx.SetPlan(p)
stmtCtx.SetPlanDigest(stmt.NormalizedPlan, stmt.PlanDigest)
sctx.GetPlanCache(isGeneralPlanCache).Put(cacheKey, cached, paramTypes)
=======
cached := NewPlanCacheValue(p, names, stmtCtx.TblInfo2UnionScan, matchOpts)
stmt.NormalizedPlan, stmt.PlanDigest = NormalizePlan(p)
stmtCtx.SetPlan(p)
stmtCtx.SetPlanDigest(stmt.NormalizedPlan, stmt.PlanDigest)
sctx.GetPlanCache(isNonPrepared).Put(cacheKey, cached, matchOpts)
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
}
sessVars.FoundInPlanCache = false
return p, names, err
Expand Down
40 changes: 39 additions & 1 deletion planner/core/plan_cache_lru.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import (
"github.com/pingcap/errors"
"github.com/pingcap/tidb/metrics"
"github.com/pingcap/tidb/sessionctx"
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/util/hack"
"github.com/pingcap/tidb/util/kvcache"
"github.com/pingcap/tidb/util/logutil"
"github.com/pingcap/tidb/util/memory"
utilpc "github.com/pingcap/tidb/util/plancache"
)

// planCacheEntry wraps Key and Value. It's the value of list.Element.
Expand Down Expand Up @@ -94,13 +94,21 @@ func strHashKey(key kvcache.Key, deepCopy bool) string {
}

// Get tries to find the corresponding value according to the given key.
<<<<<<< HEAD
func (l *LRUPlanCache) Get(key kvcache.Key, paramTypes []*types.FieldType) (value kvcache.Value, ok bool) {
=======
func (l *LRUPlanCache) Get(key kvcache.Key, opts *utilpc.PlanCacheMatchOpts) (value kvcache.Value, ok bool) {
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
l.lock.Lock()
defer l.lock.Unlock()

bucket, bucketExist := l.buckets[strHashKey(key, false)]
if bucketExist {
<<<<<<< HEAD
if element, exist := l.pickFromBucket(bucket, paramTypes); exist {
=======
if element, exist := l.pickFromBucket(bucket, opts); exist {
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
l.lruList.MoveToFront(element)
return element.Value.(*planCacheEntry).PlanValue, true
}
Expand All @@ -109,14 +117,22 @@ func (l *LRUPlanCache) Get(key kvcache.Key, paramTypes []*types.FieldType) (valu
}

// Put puts the (key, value) pair into the LRU Cache.
<<<<<<< HEAD
func (l *LRUPlanCache) Put(key kvcache.Key, value kvcache.Value, paramTypes []*types.FieldType) {
=======
func (l *LRUPlanCache) Put(key kvcache.Key, value kvcache.Value, opts *utilpc.PlanCacheMatchOpts) {
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
l.lock.Lock()
defer l.lock.Unlock()

hash := strHashKey(key, true)
bucket, bucketExist := l.buckets[hash]
if bucketExist {
<<<<<<< HEAD
if element, exist := l.pickFromBucket(bucket, paramTypes); exist {
=======
if element, exist := l.pickFromBucket(bucket, opts); exist {
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
l.updateInstanceMetric(&planCacheEntry{PlanKey: key, PlanValue: value}, element.Value.(*planCacheEntry))
element.Value.(*planCacheEntry).PlanValue = value
l.lruList.MoveToFront(element)
Expand Down Expand Up @@ -252,12 +268,34 @@ func (l *LRUPlanCache) memoryControl() {
}

// PickPlanFromBucket pick one plan from bucket
<<<<<<< HEAD
func PickPlanFromBucket(bucket map[*list.Element]struct{}, paramTypes []*types.FieldType) (*list.Element, bool) {
for k := range bucket {
plan := k.Value.(*planCacheEntry).PlanValue.(*PlanCacheValue)
if plan.ParamTypes.CheckTypesCompatibility4PC(paramTypes) {
return k, true
}
=======
func (l *LRUPlanCache) pickFromBucket(bucket map[*list.Element]struct{}, matchOpts *utilpc.PlanCacheMatchOpts) (*list.Element, bool) {
for k := range bucket {
plan := k.Value.(*planCacheEntry).PlanValue.(*PlanCacheValue)
// check param types' compatibility
ok1 := checkTypesCompatibility4PC(plan.matchOpts.ParamTypes, matchOpts.ParamTypes)
if !ok1 {
continue
}

// check limit offset and key if equal and check switch if enabled
ok2 := checkUint64SliceIfEqual(plan.matchOpts.LimitOffsetAndCount, matchOpts.LimitOffsetAndCount)
if !ok2 {
continue
}
if len(plan.matchOpts.LimitOffsetAndCount) > 0 && !l.sctx.GetSessionVars().EnablePlanCacheForParamLimit {
// offset and key slice matched, but it is a plan with param limit and the switch is disabled
continue
}
return k, true
>>>>>>> 12107e33d3 (planner: refactor plan cache LRU code (#41618))
}
return nil, false
}
Expand Down
Loading