github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/statistics/handle/dump.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 handle 15 16 import ( 17 "time" 18 19 "github.com/whtcorpsinc/errors" 20 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 21 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 22 "github.com/whtcorpsinc/milevadb/schemareplicant" 23 "github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx" 24 "github.com/whtcorpsinc/milevadb/statistics" 25 "github.com/whtcorpsinc/milevadb/types" 26 "github.com/whtcorpsinc/milevadb/soliton/sqlexec" 27 "github.com/whtcorpsinc/fidelpb/go-fidelpb" 28 ) 29 30 // JSONTable is used for dumping statistics. 31 type JSONTable struct { 32 DatabaseName string `json:"database_name"` 33 TableName string `json:"block_name"` 34 DeferredCausets map[string]*jsonDeferredCauset `json:"columns"` 35 Indices map[string]*jsonDeferredCauset `json:"indices"` 36 Count int64 `json:"count"` 37 ModifyCount int64 `json:"modify_count"` 38 Partitions map[string]*JSONTable `json:"partitions"` 39 } 40 41 type jsonDeferredCauset struct { 42 Histogram *fidelpb.Histogram `json:"histogram"` 43 CMSketch *fidelpb.CMSketch `json:"cm_sketch"` 44 NullCount int64 `json:"null_count"` 45 TotDefCausSize int64 `json:"tot_col_size"` 46 LastUFIDelateVersion uint64 `json:"last_uFIDelate_version"` 47 Correlation float64 `json:"correlation"` 48 } 49 50 func dumpJSONDefCaus(hist *statistics.Histogram, CMSketch *statistics.CMSketch) *jsonDeferredCauset { 51 jsonDefCaus := &jsonDeferredCauset{ 52 Histogram: statistics.HistogramToProto(hist), 53 NullCount: hist.NullCount, 54 TotDefCausSize: hist.TotDefCausSize, 55 LastUFIDelateVersion: hist.LastUFIDelateVersion, 56 Correlation: hist.Correlation, 57 } 58 if CMSketch != nil { 59 jsonDefCaus.CMSketch = statistics.CMSketchToProto(CMSketch) 60 } 61 return jsonDefCaus 62 } 63 64 // DumpStatsToJSON dumps statistic to json. 65 func (h *Handle) DumpStatsToJSON(dbName string, blockInfo *perceptron.TableInfo, historyStatsInterDirc sqlexec.RestrictedALLEGROSQLInterlockingDirectorate) (*JSONTable, error) { 66 pi := blockInfo.GetPartitionInfo() 67 if pi == nil { 68 return h.blockStatsToJSON(dbName, blockInfo, blockInfo.ID, historyStatsInterDirc) 69 } 70 jsonTbl := &JSONTable{ 71 DatabaseName: dbName, 72 TableName: blockInfo.Name.L, 73 Partitions: make(map[string]*JSONTable, len(pi.Definitions)), 74 } 75 for _, def := range pi.Definitions { 76 tbl, err := h.blockStatsToJSON(dbName, blockInfo, def.ID, historyStatsInterDirc) 77 if err != nil { 78 return nil, errors.Trace(err) 79 } 80 if tbl == nil { 81 continue 82 } 83 jsonTbl.Partitions[def.Name.L] = tbl 84 } 85 return jsonTbl, nil 86 } 87 88 func (h *Handle) blockStatsToJSON(dbName string, blockInfo *perceptron.TableInfo, physicalID int64, historyStatsInterDirc sqlexec.RestrictedALLEGROSQLInterlockingDirectorate) (*JSONTable, error) { 89 tbl, err := h.blockStatsFromStorage(blockInfo, physicalID, true, historyStatsInterDirc) 90 if err != nil || tbl == nil { 91 return nil, err 92 } 93 tbl.Version, tbl.ModifyCount, tbl.Count, err = h.statsMetaByTableIDFromStorage(physicalID, historyStatsInterDirc) 94 if err != nil { 95 return nil, err 96 } 97 jsonTbl := &JSONTable{ 98 DatabaseName: dbName, 99 TableName: blockInfo.Name.L, 100 DeferredCausets: make(map[string]*jsonDeferredCauset, len(tbl.DeferredCausets)), 101 Indices: make(map[string]*jsonDeferredCauset, len(tbl.Indices)), 102 Count: tbl.Count, 103 ModifyCount: tbl.ModifyCount, 104 } 105 106 for _, col := range tbl.DeferredCausets { 107 sc := &stmtctx.StatementContext{TimeZone: time.UTC} 108 hist, err := col.ConvertTo(sc, types.NewFieldType(allegrosql.TypeBlob)) 109 if err != nil { 110 return nil, errors.Trace(err) 111 } 112 jsonTbl.DeferredCausets[col.Info.Name.L] = dumpJSONDefCaus(hist, col.CMSketch) 113 } 114 115 for _, idx := range tbl.Indices { 116 jsonTbl.Indices[idx.Info.Name.L] = dumpJSONDefCaus(&idx.Histogram, idx.CMSketch) 117 } 118 return jsonTbl, nil 119 } 120 121 // LoadStatsFromJSON will load statistic from JSONTable, and save it to the storage. 122 func (h *Handle) LoadStatsFromJSON(is schemareplicant.SchemaReplicant, jsonTbl *JSONTable) error { 123 causet, err := is.TableByName(perceptron.NewCIStr(jsonTbl.DatabaseName), perceptron.NewCIStr(jsonTbl.TableName)) 124 if err != nil { 125 return errors.Trace(err) 126 } 127 blockInfo := causet.Meta() 128 pi := blockInfo.GetPartitionInfo() 129 if pi == nil { 130 err := h.loadStatsFromJSON(blockInfo, blockInfo.ID, jsonTbl) 131 if err != nil { 132 return errors.Trace(err) 133 } 134 } else { 135 if jsonTbl.Partitions == nil { 136 return errors.New("No partition statistics") 137 } 138 for _, def := range pi.Definitions { 139 tbl := jsonTbl.Partitions[def.Name.L] 140 if tbl == nil { 141 continue 142 } 143 err := h.loadStatsFromJSON(blockInfo, def.ID, tbl) 144 if err != nil { 145 return errors.Trace(err) 146 } 147 } 148 } 149 return errors.Trace(h.UFIDelate(is)) 150 } 151 152 func (h *Handle) loadStatsFromJSON(blockInfo *perceptron.TableInfo, physicalID int64, jsonTbl *JSONTable) error { 153 tbl, err := TableStatsFromJSON(blockInfo, physicalID, jsonTbl) 154 if err != nil { 155 return errors.Trace(err) 156 } 157 158 for _, col := range tbl.DeferredCausets { 159 err = h.SaveStatsToStorage(tbl.PhysicalID, tbl.Count, 0, &col.Histogram, col.CMSketch, 1) 160 if err != nil { 161 return errors.Trace(err) 162 } 163 } 164 for _, idx := range tbl.Indices { 165 err = h.SaveStatsToStorage(tbl.PhysicalID, tbl.Count, 1, &idx.Histogram, idx.CMSketch, 1) 166 if err != nil { 167 return errors.Trace(err) 168 } 169 } 170 err = h.SaveMetaToStorage(tbl.PhysicalID, tbl.Count, tbl.ModifyCount) 171 return err 172 } 173 174 // TableStatsFromJSON loads statistic from JSONTable and return the Block of statistic. 175 func TableStatsFromJSON(blockInfo *perceptron.TableInfo, physicalID int64, jsonTbl *JSONTable) (*statistics.Block, error) { 176 newHistDefCausl := statistics.HistDefCausl{ 177 PhysicalID: physicalID, 178 HavePhysicalID: true, 179 Count: jsonTbl.Count, 180 ModifyCount: jsonTbl.ModifyCount, 181 DeferredCausets: make(map[int64]*statistics.DeferredCauset, len(jsonTbl.DeferredCausets)), 182 Indices: make(map[int64]*statistics.Index, len(jsonTbl.Indices)), 183 } 184 tbl := &statistics.Block{ 185 HistDefCausl: newHistDefCausl, 186 } 187 for id, jsonIdx := range jsonTbl.Indices { 188 for _, idxInfo := range blockInfo.Indices { 189 if idxInfo.Name.L != id { 190 continue 191 } 192 hist := statistics.HistogramFromProto(jsonIdx.Histogram) 193 hist.ID, hist.NullCount, hist.LastUFIDelateVersion, hist.Correlation = idxInfo.ID, jsonIdx.NullCount, jsonIdx.LastUFIDelateVersion, jsonIdx.Correlation 194 idx := &statistics.Index{ 195 Histogram: *hist, 196 CMSketch: statistics.CMSketchFromProto(jsonIdx.CMSketch), 197 Info: idxInfo, 198 } 199 tbl.Indices[idx.ID] = idx 200 } 201 } 202 203 for id, jsonDefCaus := range jsonTbl.DeferredCausets { 204 for _, colInfo := range blockInfo.DeferredCausets { 205 if colInfo.Name.L != id { 206 continue 207 } 208 hist := statistics.HistogramFromProto(jsonDefCaus.Histogram) 209 count := int64(hist.TotalRowCount()) 210 sc := &stmtctx.StatementContext{TimeZone: time.UTC} 211 hist, err := hist.ConvertTo(sc, &colInfo.FieldType) 212 if err != nil { 213 return nil, errors.Trace(err) 214 } 215 hist.ID, hist.NullCount, hist.LastUFIDelateVersion, hist.TotDefCausSize, hist.Correlation = colInfo.ID, jsonDefCaus.NullCount, jsonDefCaus.LastUFIDelateVersion, jsonDefCaus.TotDefCausSize, jsonDefCaus.Correlation 216 col := &statistics.DeferredCauset{ 217 PhysicalID: physicalID, 218 Histogram: *hist, 219 CMSketch: statistics.CMSketchFromProto(jsonDefCaus.CMSketch), 220 Info: colInfo, 221 Count: count, 222 IsHandle: blockInfo.PKIsHandle && allegrosql.HasPriKeyFlag(colInfo.Flag), 223 } 224 tbl.DeferredCausets[col.ID] = col 225 } 226 } 227 return tbl, nil 228 }