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 }