github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/interlock/show_stats.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 interlock 15 16 import ( 17 "time" 18 19 "github.com/whtcorpsinc/errors" 20 "github.com/whtcorpsinc/milevadb/petri" 21 "github.com/whtcorpsinc/milevadb/statistics" 22 "github.com/whtcorpsinc/milevadb/causetstore/einsteindb/oracle" 23 "github.com/whtcorpsinc/milevadb/types" 24 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 25 ) 26 27 func (e *ShowInterDirc) fetchShowStatsMeta() error { 28 do := petri.GetPetri(e.ctx) 29 h := do.StatsHandle() 30 dbs := do.SchemaReplicant().AllSchemas() 31 for _, EDB := range dbs { 32 for _, tbl := range EDB.Blocks { 33 pi := tbl.GetPartitionInfo() 34 if pi == nil { 35 e.appendBlockForStatsMeta(EDB.Name.O, tbl.Name.O, "", h.GetBlockStats(tbl)) 36 } else { 37 for _, def := range pi.Definitions { 38 e.appendBlockForStatsMeta(EDB.Name.O, tbl.Name.O, def.Name.O, h.GetPartitionStats(tbl, def.ID)) 39 } 40 } 41 } 42 } 43 return nil 44 } 45 46 func (e *ShowInterDirc) appendBlockForStatsMeta(dbName, tblName, partitionName string, statsTbl *statistics.Block) { 47 if statsTbl.Pseudo { 48 return 49 } 50 e.appendEvent([]interface{}{ 51 dbName, 52 tblName, 53 partitionName, 54 e.versionToTime(statsTbl.Version), 55 statsTbl.ModifyCount, 56 statsTbl.Count, 57 }) 58 } 59 60 func (e *ShowInterDirc) fetchShowStatsHistogram() error { 61 do := petri.GetPetri(e.ctx) 62 h := do.StatsHandle() 63 dbs := do.SchemaReplicant().AllSchemas() 64 for _, EDB := range dbs { 65 for _, tbl := range EDB.Blocks { 66 pi := tbl.GetPartitionInfo() 67 if pi == nil { 68 e.appendBlockForStatsHistograms(EDB.Name.O, tbl.Name.O, "", h.GetBlockStats(tbl)) 69 } else { 70 for _, def := range pi.Definitions { 71 e.appendBlockForStatsHistograms(EDB.Name.O, tbl.Name.O, def.Name.O, h.GetPartitionStats(tbl, def.ID)) 72 } 73 } 74 } 75 } 76 return nil 77 } 78 79 func (e *ShowInterDirc) appendBlockForStatsHistograms(dbName, tblName, partitionName string, statsTbl *statistics.Block) { 80 if statsTbl.Pseudo { 81 return 82 } 83 for _, defCaus := range statsTbl.DeferredCausets { 84 // Pass a nil StatementContext to avoid defCausumn stats being marked as needed. 85 if defCaus.IsInvalid(nil, false) { 86 continue 87 } 88 e.histogramToEvent(dbName, tblName, partitionName, defCaus.Info.Name.O, 0, defCaus.Histogram, defCaus.AvgDefCausSize(statsTbl.Count, false)) 89 } 90 for _, idx := range statsTbl.Indices { 91 e.histogramToEvent(dbName, tblName, partitionName, idx.Info.Name.O, 1, idx.Histogram, 0) 92 } 93 } 94 95 func (e *ShowInterDirc) histogramToEvent(dbName, tblName, partitionName, defCausName string, isIndex int, hist statistics.Histogram, avgDefCausSize float64) { 96 e.appendEvent([]interface{}{ 97 dbName, 98 tblName, 99 partitionName, 100 defCausName, 101 isIndex, 102 e.versionToTime(hist.LastUFIDelateVersion), 103 hist.NDV, 104 hist.NullCount, 105 avgDefCausSize, 106 hist.Correlation, 107 }) 108 } 109 110 func (e *ShowInterDirc) versionToTime(version uint64) types.Time { 111 t := time.Unix(0, oracle.ExtractPhysical(version)*int64(time.Millisecond)) 112 return types.NewTime(types.FromGoTime(t), allegrosql.TypeDatetime, 0) 113 } 114 115 func (e *ShowInterDirc) fetchShowStatsBuckets() error { 116 do := petri.GetPetri(e.ctx) 117 h := do.StatsHandle() 118 dbs := do.SchemaReplicant().AllSchemas() 119 for _, EDB := range dbs { 120 for _, tbl := range EDB.Blocks { 121 pi := tbl.GetPartitionInfo() 122 if pi == nil { 123 if err := e.appendBlockForStatsBuckets(EDB.Name.O, tbl.Name.O, "", h.GetBlockStats(tbl)); err != nil { 124 return err 125 } 126 } else { 127 for _, def := range pi.Definitions { 128 if err := e.appendBlockForStatsBuckets(EDB.Name.O, tbl.Name.O, def.Name.O, h.GetPartitionStats(tbl, def.ID)); err != nil { 129 return err 130 } 131 } 132 } 133 } 134 } 135 return nil 136 } 137 138 func (e *ShowInterDirc) appendBlockForStatsBuckets(dbName, tblName, partitionName string, statsTbl *statistics.Block) error { 139 if statsTbl.Pseudo { 140 return nil 141 } 142 defCausNameToType := make(map[string]byte, len(statsTbl.DeferredCausets)) 143 for _, defCaus := range statsTbl.DeferredCausets { 144 err := e.bucketsToEvents(dbName, tblName, partitionName, defCaus.Info.Name.O, 0, defCaus.Histogram, nil) 145 if err != nil { 146 return errors.Trace(err) 147 } 148 defCausNameToType[defCaus.Info.Name.O] = defCaus.Histogram.Tp.Tp 149 } 150 for _, idx := range statsTbl.Indices { 151 idxDeferredCausetTypes := make([]byte, 0, len(idx.Info.DeferredCausets)) 152 for i := 0; i < len(idx.Info.DeferredCausets); i++ { 153 idxDeferredCausetTypes = append(idxDeferredCausetTypes, defCausNameToType[idx.Info.DeferredCausets[i].Name.O]) 154 } 155 err := e.bucketsToEvents(dbName, tblName, partitionName, idx.Info.Name.O, len(idx.Info.DeferredCausets), idx.Histogram, idxDeferredCausetTypes) 156 if err != nil { 157 return errors.Trace(err) 158 } 159 } 160 return nil 161 } 162 163 // bucketsToEvents converts histogram buckets to rows. If the histogram is built from index, then numOfDefCauss equals to number 164 // of index defCausumns, else numOfDefCauss is 0. 165 func (e *ShowInterDirc) bucketsToEvents(dbName, tblName, partitionName, defCausName string, numOfDefCauss int, hist statistics.Histogram, idxDeferredCausetTypes []byte) error { 166 isIndex := 0 167 if numOfDefCauss > 0 { 168 isIndex = 1 169 } 170 for i := 0; i < hist.Len(); i++ { 171 lowerBoundStr, err := statistics.ValueToString(e.ctx.GetStochastikVars(), hist.GetLower(i), numOfDefCauss, idxDeferredCausetTypes) 172 if err != nil { 173 return errors.Trace(err) 174 } 175 upperBoundStr, err := statistics.ValueToString(e.ctx.GetStochastikVars(), hist.GetUpper(i), numOfDefCauss, idxDeferredCausetTypes) 176 if err != nil { 177 return errors.Trace(err) 178 } 179 e.appendEvent([]interface{}{ 180 dbName, 181 tblName, 182 partitionName, 183 defCausName, 184 isIndex, 185 i, 186 hist.Buckets[i].Count, 187 hist.Buckets[i].Repeat, 188 lowerBoundStr, 189 upperBoundStr, 190 }) 191 } 192 return nil 193 } 194 195 func (e *ShowInterDirc) fetchShowStatsHealthy() { 196 do := petri.GetPetri(e.ctx) 197 h := do.StatsHandle() 198 dbs := do.SchemaReplicant().AllSchemas() 199 for _, EDB := range dbs { 200 for _, tbl := range EDB.Blocks { 201 pi := tbl.GetPartitionInfo() 202 if pi == nil { 203 e.appendBlockForStatsHealthy(EDB.Name.O, tbl.Name.O, "", h.GetBlockStats(tbl)) 204 } else { 205 for _, def := range pi.Definitions { 206 e.appendBlockForStatsHealthy(EDB.Name.O, tbl.Name.O, def.Name.O, h.GetPartitionStats(tbl, def.ID)) 207 } 208 } 209 } 210 } 211 } 212 213 func (e *ShowInterDirc) appendBlockForStatsHealthy(dbName, tblName, partitionName string, statsTbl *statistics.Block) { 214 if statsTbl.Pseudo { 215 return 216 } 217 var healthy int64 218 if statsTbl.ModifyCount < statsTbl.Count { 219 healthy = int64((1.0 - float64(statsTbl.ModifyCount)/float64(statsTbl.Count)) * 100.0) 220 } else if statsTbl.ModifyCount == 0 { 221 healthy = 100 222 } 223 e.appendEvent([]interface{}{ 224 dbName, 225 tblName, 226 partitionName, 227 healthy, 228 }) 229 } 230 231 func (e *ShowInterDirc) fetchShowAnalyzeStatus() { 232 rows := dataForAnalyzeStatusHelper(e.baseInterlockingDirectorate.ctx) 233 for _, event := range rows { 234 for i, val := range event { 235 e.result.AppendCauset(i, &val) 236 } 237 } 238 }