planner: refactor a few code of plan cache (#54058)

ref pingcap/tidb#54057
This commit is contained in:
Yuanjia Zhang
2024-06-18 10:13:16 +08:00
committed by GitHub
parent e7d67b198f
commit 42852ee632
2 changed files with 35 additions and 49 deletions

View File

@ -253,61 +253,13 @@ 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
if matchCachedPlan(l.sctx, k.Value.(*planCacheEntry).PlanValue.(*PlanCacheValue), matchOpts) {
return k, true
}
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
}
// check subquery switch state
if plan.matchOpts.HasSubQuery && !l.sctx.GetSessionVars().EnablePlanCacheForSubquery {
continue
}
// table stats has changed
// this check can be disabled by turning off system variable tidb_plan_cache_invalidation_on_fresh_stats
if l.sctx.GetSessionVars().PlanCacheInvalidationOnFreshStats &&
plan.matchOpts.StatsVersionHash != matchOpts.StatsVersionHash {
continue
}
// below are some SQL variables that can affect the plan
if plan.matchOpts.ForeignKeyChecks != matchOpts.ForeignKeyChecks {
continue
}
return k, true
}
return nil, false
}
func checkUint64SliceIfEqual(a, b []uint64) bool {
if (a == nil && b != nil) || (a != nil && b == nil) {
return false
}
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
// updateInstanceMetric update the memory usage and plan num for show in grafana
func (l *LRUPlanCache) updateInstanceMetric(in, out *planCacheEntry) {
updateInstancePlanNum(in, out)

View File

@ -750,3 +750,37 @@ func parseParamTypes(sctx sessionctx.Context, params []expression.Expression) (p
}
return
}
// matchCachedPlan checks whether this plan is matched with these match-options.
func matchCachedPlan(sctx sessionctx.Context, value *PlanCacheValue, matchOpts *utilpc.PlanCacheMatchOpts) bool {
if matchOpts == nil { // if PointGet, the matchOpts is nil
return true
}
if !checkTypesCompatibility4PC(value.matchOpts.ParamTypes, matchOpts.ParamTypes) {
return false
}
// check limit offset and key if equal and check switch if enabled
if !slices.Equal(value.matchOpts.LimitOffsetAndCount, matchOpts.LimitOffsetAndCount) {
return false
}
if len(value.matchOpts.LimitOffsetAndCount) > 0 && !sctx.GetSessionVars().EnablePlanCacheForParamLimit {
// offset and key slice matched, but it is a plan with param limit and the switch is disabled
return false
}
// check subquery switch state
if value.matchOpts.HasSubQuery && !sctx.GetSessionVars().EnablePlanCacheForSubquery {
return false
}
// table stats has changed
// this check can be disabled by turning off system variable tidb_plan_cache_invalidation_on_fresh_stats
if sctx.GetSessionVars().PlanCacheInvalidationOnFreshStats &&
value.matchOpts.StatsVersionHash != matchOpts.StatsVersionHash {
return false
}
// below are some SQL variables that can affect the plan
if value.matchOpts.ForeignKeyChecks != matchOpts.ForeignKeyChecks {
return false
}
return true
}