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 a few code of plan cache #54058

Merged
merged 3 commits into from
Jun 18, 2024
Merged
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
50 changes: 1 addition & 49 deletions pkg/planner/core/plan_cache_lru.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
34 changes: 34 additions & 0 deletions pkg/planner/core/plan_cache_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}