Skip to content

Commit

Permalink
planner: introduce a interface for binding cache (#51351)
Browse files Browse the repository at this point in the history
ref #51347
  • Loading branch information
qw4990 authored Feb 27, 2024
1 parent fbc3c7e commit c663937
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 10 deletions.
29 changes: 26 additions & 3 deletions pkg/bindinfo/binding_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,28 @@ import (
"github.com/pingcap/tidb/pkg/util/memory"
)

// BindingCache is the interface for the cache of the SQL plan bindings.
type BindingCache interface {
// GetBinding gets the binding for the specified sqlDigest.
GetBinding(sqlDigest string) Bindings
// GetAllBindings gets all the bindings in the cache.
GetAllBindings() Bindings
// SetBinding sets the binding for the specified sqlDigest.
SetBinding(sqlDigest string, meta Bindings) (err error)
// RemoveBinding removes the binding for the specified sqlDigest.
RemoveBinding(sqlDigest string)
// SetMemCapacity sets the memory capacity for the cache.
SetMemCapacity(capacity int64)
// GetMemUsage gets the memory usage of the cache.
GetMemUsage() int64
// GetMemCapacity gets the memory capacity of the cache.
GetMemCapacity() int64
// Copy copies the cache.
Copy() (newCache BindingCache, err error)
// Size returns the number of items in the cache.
Size() int
}

// bindingCache uses the LRU cache to store the bindings.
// The key of the LRU cache is original sql, the value is a slice of Bindings.
// Note: The bindingCache should be accessed with lock.
Expand All @@ -47,7 +69,7 @@ func calcBindCacheKVMem(key bindingCacheKey, value Bindings) int64 {
return int64(len(key.Hash())) + valMem
}

func newBindCache() *bindingCache {
func newBindCache() BindingCache {
// since bindingCache controls the memory usage by itself, set the capacity of
// the underlying LRUCache to max to close its memory control
cache := kvcache.NewSimpleLRUCache(mathutil.MaxUint, 0, 0)
Expand Down Expand Up @@ -181,10 +203,11 @@ func (c *bindingCache) GetMemCapacity() int64 {

// Copy copies a new bindingCache from the origin cache.
// The function is thread-safe.
func (c *bindingCache) Copy() (newCache *bindingCache, err error) {
func (c *bindingCache) Copy() (BindingCache, error) {
c.lock.Lock()
defer c.lock.Unlock()
newCache = newBindCache()
var err error
newCache := newBindCache().(*bindingCache)
if c.memTracker.BytesConsumed() > newCache.GetMemCapacity() {
err = errors.New("The memory usage of all available bindings exceeds the cache's mem quota. As a result, all available bindings cannot be held on the cache. Please increase the value of the system variable 'tidb_mem_quota_binding_cache' and execute 'admin reload bindings' to ensure that all bindings exist in the cache and can be used normally")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/bindinfo/binding_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (

func TestBindCache(t *testing.T) {
variable.MemQuotaBindingCache.Store(250)
bindCache := newBindCache()
bindCache := newBindCache().(*bindingCache)

value := make([]Bindings, 3)
key := make([]bindingCacheKey, 3)
Expand Down
10 changes: 5 additions & 5 deletions pkg/bindinfo/global_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ type GlobalBindingHandle interface {
type globalBindingHandle struct {
sPool SessionPool

bindingCache atomic.Pointer[bindingCache]
bindingCache atomic.Value

// fuzzyDigestMap is used to support fuzzy matching.
// fuzzyDigest is the digest calculated after eliminating all DB names, e.g. `select * from test.t` -> `select * from t` -> fuzzyDigest.
Expand Down Expand Up @@ -156,11 +156,11 @@ func NewGlobalBindingHandle(sPool SessionPool) GlobalBindingHandle {
return handle
}

func (h *globalBindingHandle) getCache() *bindingCache {
return h.bindingCache.Load()
func (h *globalBindingHandle) getCache() BindingCache {
return h.bindingCache.Load().(BindingCache)
}

func (h *globalBindingHandle) setCache(c *bindingCache) {
func (h *globalBindingHandle) setCache(c BindingCache) {
// TODO: update the global cache in-place instead of replacing it and remove this function.
h.bindingCache.Store(c)
}
Expand Down Expand Up @@ -209,7 +209,7 @@ func (h *globalBindingHandle) setLastUpdateTime(t types.Time) {
func (h *globalBindingHandle) LoadFromStorageToCache(fullLoad bool) (err error) {
var lastUpdateTime types.Time
var timeCondition string
var newCache *bindingCache
var newCache BindingCache
if fullLoad {
lastUpdateTime = types.ZeroTimestamp
timeCondition = ""
Expand Down
2 changes: 1 addition & 1 deletion pkg/bindinfo/session_handle.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ type SessionBindingHandle interface {

// sessionBindingHandle is used to handle all session sql bind operations.
type sessionBindingHandle struct {
ch *bindingCache
ch BindingCache
}

// NewSessionBindingHandle creates a new SessionBindingHandle.
Expand Down

0 comments on commit c663937

Please sign in to comment.