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  }