github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/stats/new_stat.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package stats
    12  
    13  import (
    14  	"context"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/gossip"
    17  	"github.com/cockroachdb/cockroach/pkg/kv"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/sqlutil"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    22  	"github.com/cockroachdb/cockroach/pkg/util/protoutil"
    23  )
    24  
    25  // InsertNewStats inserts a slice of statistics at the current time into the
    26  // system table.
    27  func InsertNewStats(
    28  	ctx context.Context,
    29  	executor sqlutil.InternalExecutor,
    30  	txn *kv.Txn,
    31  	tableStats []*TableStatisticProto,
    32  ) error {
    33  	var err error
    34  	for _, statistic := range tableStats {
    35  		err = InsertNewStat(
    36  			ctx,
    37  			executor,
    38  			txn,
    39  			statistic.TableID,
    40  			statistic.Name,
    41  			statistic.ColumnIDs,
    42  			int64(statistic.RowCount),
    43  			int64(statistic.DistinctCount),
    44  			int64(statistic.NullCount),
    45  			statistic.HistogramData,
    46  		)
    47  		if err != nil {
    48  			return err
    49  		}
    50  	}
    51  	return nil
    52  }
    53  
    54  // InsertNewStat inserts a new statistic in the system table.
    55  // The caller is responsible for calling GossipTableStatAdded to notify the stat
    56  // caches.
    57  func InsertNewStat(
    58  	ctx context.Context,
    59  	executor sqlutil.InternalExecutor,
    60  	txn *kv.Txn,
    61  	tableID sqlbase.ID,
    62  	name string,
    63  	columnIDs []sqlbase.ColumnID,
    64  	rowCount, distinctCount, nullCount int64,
    65  	h *HistogramData,
    66  ) error {
    67  	// We must pass a nil interface{} if we want to insert a NULL.
    68  	var nameVal, histogramVal interface{}
    69  	if name != "" {
    70  		nameVal = name
    71  	}
    72  	if h != nil {
    73  		var err error
    74  		histogramVal, err = protoutil.Marshal(h)
    75  		if err != nil {
    76  			return err
    77  		}
    78  	}
    79  
    80  	columnIDsVal := tree.NewDArray(types.Int)
    81  	for _, c := range columnIDs {
    82  		if err := columnIDsVal.Append(tree.NewDInt(tree.DInt(int(c)))); err != nil {
    83  			return err
    84  		}
    85  	}
    86  
    87  	_, err := executor.Exec(
    88  		ctx, "insert-statistic", txn,
    89  		`INSERT INTO system.table_statistics (
    90  					"tableID",
    91  					"name",
    92  					"columnIDs",
    93  					"rowCount",
    94  					"distinctCount",
    95  					"nullCount",
    96  					histogram
    97  				) VALUES ($1, $2, $3, $4, $5, $6, $7)`,
    98  		tableID,
    99  		nameVal,
   100  		columnIDsVal,
   101  		rowCount,
   102  		distinctCount,
   103  		nullCount,
   104  		histogramVal,
   105  	)
   106  	return err
   107  }
   108  
   109  // GossipTableStatAdded causes the statistic caches for this table to be
   110  // invalidated.
   111  func GossipTableStatAdded(g *gossip.Gossip, tableID sqlbase.ID) error {
   112  	// TODO(radu): perhaps use a TTL here to avoid having a key per table floating
   113  	// around forever (we would need the stat cache to evict old entries
   114  	// automatically though).
   115  	return g.AddInfo(
   116  		gossip.MakeTableStatAddedKey(uint32(tableID)),
   117  		nil, /* value */
   118  		0,   /* ttl */
   119  	)
   120  }