github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/petri/acyclic/causet/embedded/cache.go (about) 1 // Copyright 2020 WHTCORPS INC, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package embedded 15 16 import ( 17 "math" 18 "sync/atomic" 19 "time" 20 21 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 22 "github.com/whtcorpsinc/BerolinaSQL/ast" 23 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 24 "github.com/whtcorpsinc/milevadb/ekv" 25 "github.com/whtcorpsinc/milevadb/soliton/codec" 26 "github.com/whtcorpsinc/milevadb/soliton/ekvcache" 27 "github.com/whtcorpsinc/milevadb/soliton/replog" 28 "github.com/whtcorpsinc/milevadb/stochastikctx/variable" 29 "github.com/whtcorpsinc/milevadb/types" 30 atomic2 "go.uber.org/atomic" 31 ) 32 33 var ( 34 // preparedCausetCacheEnabledValue stores the global config "prepared-plan-cache-enabled". 35 // If the value of "prepared-plan-cache-enabled" is true, preparedCausetCacheEnabledValue's value is 1. 36 // Otherwise, preparedCausetCacheEnabledValue's value is 0. 37 preparedCausetCacheEnabledValue int32 38 // PreparedCausetCacheCapacity stores the global config "prepared-plan-cache-capacity". 39 PreparedCausetCacheCapacity uint = 100 40 // PreparedCausetCacheMemoryGuardRatio stores the global config "prepared-plan-cache-memory-guard-ratio". 41 PreparedCausetCacheMemoryGuardRatio = 0.1 42 // PreparedCausetCacheMaxMemory stores the max memory size defined in the global config "performance-server-memory-quota". 43 PreparedCausetCacheMaxMemory = *atomic2.NewUint64(math.MaxUint64) 44 ) 45 46 const ( 47 preparedCausetCacheEnabled = 1 48 preparedCausetCacheUnable = 0 49 ) 50 51 // SetPreparedCausetCache sets isEnabled to true, then prepared plan cache is enabled. 52 func SetPreparedCausetCache(isEnabled bool) { 53 if isEnabled { 54 atomic.StoreInt32(&preparedCausetCacheEnabledValue, preparedCausetCacheEnabled) 55 } else { 56 atomic.StoreInt32(&preparedCausetCacheEnabledValue, preparedCausetCacheUnable) 57 } 58 } 59 60 // PreparedCausetCacheEnabled returns whether the prepared plan cache is enabled. 61 func PreparedCausetCacheEnabled() bool { 62 isEnabled := atomic.LoadInt32(&preparedCausetCacheEnabledValue) 63 return isEnabled == preparedCausetCacheEnabled 64 } 65 66 type pstmtCausetCacheKey struct { 67 database string 68 connID uint64 69 pstmtID uint32 70 snapshot uint64 71 schemaVersion int64 72 sqlMode allegrosql.ALLEGROSQLMode 73 timezoneOffset int 74 isolationReadEngines map[ekv.StoreType]struct{} 75 selectLimit uint64 76 77 hash []byte 78 } 79 80 // Hash implements Key interface. 81 func (key *pstmtCausetCacheKey) Hash() []byte { 82 if len(key.hash) == 0 { 83 var ( 84 dbBytes = replog.Slice(key.database) 85 bufferSize = len(dbBytes) + 8*6 + 3*8 86 ) 87 if key.hash == nil { 88 key.hash = make([]byte, 0, bufferSize) 89 } 90 key.hash = append(key.hash, dbBytes...) 91 key.hash = codec.EncodeInt(key.hash, int64(key.connID)) 92 key.hash = codec.EncodeInt(key.hash, int64(key.pstmtID)) 93 key.hash = codec.EncodeInt(key.hash, int64(key.snapshot)) 94 key.hash = codec.EncodeInt(key.hash, key.schemaVersion) 95 key.hash = codec.EncodeInt(key.hash, int64(key.sqlMode)) 96 key.hash = codec.EncodeInt(key.hash, int64(key.timezoneOffset)) 97 if _, ok := key.isolationReadEngines[ekv.MilevaDB]; ok { 98 key.hash = append(key.hash, ekv.MilevaDB.Name()...) 99 } 100 if _, ok := key.isolationReadEngines[ekv.EinsteinDB]; ok { 101 key.hash = append(key.hash, ekv.EinsteinDB.Name()...) 102 } 103 if _, ok := key.isolationReadEngines[ekv.TiFlash]; ok { 104 key.hash = append(key.hash, ekv.TiFlash.Name()...) 105 } 106 key.hash = codec.EncodeInt(key.hash, int64(key.selectLimit)) 107 } 108 return key.hash 109 } 110 111 // SetPstmtIDSchemaVersion implements PstmtCacheKeyMutator interface to change pstmtID and schemaVersion of cacheKey. 112 // so we can reuse Key instead of new every time. 113 func SetPstmtIDSchemaVersion(key ekvcache.Key, pstmtID uint32, schemaVersion int64, isolationReadEngines map[ekv.StoreType]struct{}) { 114 psStmtKey, isPsStmtKey := key.(*pstmtCausetCacheKey) 115 if !isPsStmtKey { 116 return 117 } 118 psStmtKey.pstmtID = pstmtID 119 psStmtKey.schemaVersion = schemaVersion 120 psStmtKey.isolationReadEngines = make(map[ekv.StoreType]struct{}) 121 for k, v := range isolationReadEngines { 122 psStmtKey.isolationReadEngines[k] = v 123 } 124 psStmtKey.hash = psStmtKey.hash[:0] 125 } 126 127 // NewPSTMTCausetCacheKey creates a new pstmtCausetCacheKey object. 128 func NewPSTMTCausetCacheKey(stochastikVars *variable.StochastikVars, pstmtID uint32, schemaVersion int64) ekvcache.Key { 129 timezoneOffset := 0 130 if stochastikVars.TimeZone != nil { 131 _, timezoneOffset = time.Now().In(stochastikVars.TimeZone).Zone() 132 } 133 key := &pstmtCausetCacheKey{ 134 database: stochastikVars.CurrentDB, 135 connID: stochastikVars.ConnectionID, 136 pstmtID: pstmtID, 137 snapshot: stochastikVars.SnapshotTS, 138 schemaVersion: schemaVersion, 139 sqlMode: stochastikVars.ALLEGROSQLMode, 140 timezoneOffset: timezoneOffset, 141 isolationReadEngines: make(map[ekv.StoreType]struct{}), 142 selectLimit: stochastikVars.SelectLimit, 143 } 144 for k, v := range stochastikVars.IsolationReadEngines { 145 key.isolationReadEngines[k] = v 146 } 147 return key 148 } 149 150 // PSTMTCausetCacheValue stores the cached Statement and StmtNode. 151 type PSTMTCausetCacheValue struct { 152 Causet Causet 153 OutPutNames []*types.FieldName 154 TblInfo2UnionScan map[*perceptron.BlockInfo]bool 155 } 156 157 // NewPSTMTCausetCacheValue creates a ALLEGROSQLCacheValue. 158 func NewPSTMTCausetCacheValue(plan Causet, names []*types.FieldName, srcMap map[*perceptron.BlockInfo]bool) *PSTMTCausetCacheValue { 159 dstMap := make(map[*perceptron.BlockInfo]bool) 160 for k, v := range srcMap { 161 dstMap[k] = v 162 } 163 return &PSTMTCausetCacheValue{ 164 Causet: plan, 165 OutPutNames: names, 166 TblInfo2UnionScan: dstMap, 167 } 168 } 169 170 // CachedPrepareStmt causetstore prepared ast from PrepareInterDirc and other related fields 171 type CachedPrepareStmt struct { 172 PreparedAst *ast.Prepared 173 VisitInfos []visitInfo 174 DeferredCausetInfos interface{} 175 InterlockingDirectorate interface{} 176 NormalizedALLEGROSQL string 177 NormalizedCauset string 178 ALLEGROSQLDigest string 179 CausetDigest string 180 }