github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/storage/row_counter.go (about)

     1  // Copyright 2017 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 storage
    12  
    13  import (
    14  	"bytes"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/keys"
    17  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    18  )
    19  
    20  // RowCounter is a helper that counts how many distinct rows appear in the KVs
    21  // that is is shown via `Count`. Note: the `DataSize` field of the BulkOpSummary
    22  // is *not* populated by this and should be set separately.
    23  type RowCounter struct {
    24  	roachpb.BulkOpSummary
    25  	prev roachpb.Key
    26  }
    27  
    28  // Count examines each key passed to it and increments the running count when it
    29  // sees a key that belongs to a new row.
    30  func (r *RowCounter) Count(key roachpb.Key) error {
    31  	// EnsureSafeSplitKey is usually used to avoid splitting a row across ranges,
    32  	// by returning the row's key prefix.
    33  	// We reuse it here to count "rows" by counting when it changes.
    34  	// Non-SQL keys are returned unchanged or may error -- we ignore them, since
    35  	// non-SQL keys are obviously thus not SQL rows.
    36  	//
    37  	// TODO(ajwerner): provide a separate mechanism to determine whether the key
    38  	// is a valid SQL key which explicitly indicates whether the key is valid as
    39  	// a split key independent of an error. See #43423.
    40  	row, err := keys.EnsureSafeSplitKey(key)
    41  	if err != nil || len(key) == len(row) {
    42  		// TODO(ajwerner): Determine which errors should be ignored and only
    43  		// ignore those.
    44  		return nil //nolint:returnerrcheck
    45  	}
    46  
    47  	// no change key prefix => no new row.
    48  	if bytes.Equal(row, r.prev) {
    49  		return nil
    50  	}
    51  
    52  	r.prev = append(r.prev[:0], row...)
    53  
    54  	rem, _, err := keys.DecodeTenantPrefix(row)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	_, tableID, indexID, err := keys.DecodeTableIDIndexID(rem)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	if r.EntryCounts == nil {
    64  		r.EntryCounts = make(map[uint64]int64)
    65  	}
    66  	r.EntryCounts[roachpb.BulkOpSummaryID(uint64(tableID), uint64(indexID))]++
    67  
    68  	if indexID == 1 {
    69  		r.DeprecatedRows++
    70  	} else {
    71  		r.DeprecatedIndexEntries++
    72  	}
    73  
    74  	return nil
    75  }