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

     1  // Copyright 2016 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 rowexec
    12  
    13  import (
    14  	"context"
    15  
    16  	"github.com/cockroachdb/cockroach/pkg/kv"
    17  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/kvserverbase"
    18  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    19  	"github.com/cockroachdb/cockroach/pkg/settings"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/backfill"
    21  	"github.com/cockroachdb/cockroach/pkg/sql/execinfra"
    22  	"github.com/cockroachdb/cockroach/pkg/sql/execinfrapb"
    23  	"github.com/cockroachdb/cockroach/pkg/sql/row"
    24  	"github.com/cockroachdb/cockroach/pkg/sql/sqlbase"
    25  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    26  	"github.com/cockroachdb/cockroach/pkg/util/log"
    27  	"github.com/cockroachdb/cockroach/pkg/util/timeutil"
    28  	"github.com/cockroachdb/cockroach/pkg/util/tracing"
    29  	"github.com/cockroachdb/errors"
    30  )
    31  
    32  // indexBackfiller is a processor that backfills new indexes.
    33  type indexBackfiller struct {
    34  	backfiller
    35  
    36  	backfill.IndexBackfiller
    37  
    38  	adder kvserverbase.BulkAdder
    39  
    40  	desc *sqlbase.ImmutableTableDescriptor
    41  }
    42  
    43  var _ execinfra.Processor = &indexBackfiller{}
    44  var _ chunkBackfiller = &indexBackfiller{}
    45  
    46  var backfillerBufferSize = settings.RegisterByteSizeSetting(
    47  	"schemachanger.backfiller.buffer_size", "the initial size of the BulkAdder buffer handling index backfills", 32<<20,
    48  )
    49  
    50  var backfillerMaxBufferSize = settings.RegisterByteSizeSetting(
    51  	"schemachanger.backfiller.max_buffer_size", "the maximum size of the BulkAdder buffer handling index backfills", 512<<20,
    52  )
    53  
    54  var backfillerBufferIncrementSize = settings.RegisterByteSizeSetting(
    55  	"schemachanger.backfiller.buffer_increment", "the size by which the BulkAdder attempts to grow its buffer before flushing", 32<<20,
    56  )
    57  
    58  var backillerSSTSize = settings.RegisterByteSizeSetting(
    59  	"schemachanger.backfiller.max_sst_size", "target size for ingested files during backfills", 16<<20,
    60  )
    61  
    62  func newIndexBackfiller(
    63  	flowCtx *execinfra.FlowCtx,
    64  	processorID int32,
    65  	spec execinfrapb.BackfillerSpec,
    66  	post *execinfrapb.PostProcessSpec,
    67  	output execinfra.RowReceiver,
    68  ) (*indexBackfiller, error) {
    69  	ib := &indexBackfiller{
    70  		desc: sqlbase.NewImmutableTableDescriptor(spec.Table),
    71  		backfiller: backfiller{
    72  			name:        "Index",
    73  			filter:      backfill.IndexMutationFilter,
    74  			flowCtx:     flowCtx,
    75  			processorID: processorID,
    76  			output:      output,
    77  			spec:        spec,
    78  		},
    79  	}
    80  	ib.backfiller.chunks = ib
    81  
    82  	if err := ib.IndexBackfiller.Init(flowCtx.NewEvalCtx(), ib.desc); err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	return ib, nil
    87  }
    88  
    89  func (ib *indexBackfiller) prepare(ctx context.Context) error {
    90  	minBufferSize := backfillerBufferSize.Get(&ib.flowCtx.Cfg.Settings.SV)
    91  	maxBufferSize := func() int64 { return backfillerMaxBufferSize.Get(&ib.flowCtx.Cfg.Settings.SV) }
    92  	sstSize := func() int64 { return backillerSSTSize.Get(&ib.flowCtx.Cfg.Settings.SV) }
    93  	stepSize := backfillerBufferIncrementSize.Get(&ib.flowCtx.Cfg.Settings.SV)
    94  	opts := kvserverbase.BulkAdderOptions{
    95  		SSTSize:        sstSize,
    96  		MinBufferSize:  minBufferSize,
    97  		MaxBufferSize:  maxBufferSize,
    98  		StepBufferSize: stepSize,
    99  		SkipDuplicates: ib.ContainsInvertedIndex(),
   100  	}
   101  	adder, err := ib.flowCtx.Cfg.BulkAdder(ctx, ib.flowCtx.Cfg.DB, ib.spec.ReadAsOf, opts)
   102  	if err != nil {
   103  		return err
   104  	}
   105  	ib.adder = adder
   106  	return nil
   107  }
   108  
   109  func (ib *indexBackfiller) close(ctx context.Context) {
   110  	ib.adder.Close(ctx)
   111  }
   112  
   113  func (ib *indexBackfiller) flush(ctx context.Context) error {
   114  	return ib.wrapDupError(ctx, ib.adder.Flush(ctx))
   115  }
   116  
   117  func (ib *indexBackfiller) CurrentBufferFill() float32 {
   118  	return ib.adder.CurrentBufferFill()
   119  }
   120  
   121  func (ib *indexBackfiller) wrapDupError(ctx context.Context, orig error) error {
   122  	if orig == nil {
   123  		return nil
   124  	}
   125  	var typed *kvserverbase.DuplicateKeyError
   126  	if !errors.As(orig, &typed) {
   127  		return orig
   128  	}
   129  
   130  	desc, err := ib.desc.MakeFirstMutationPublic(sqlbase.IncludeConstraints)
   131  	immutable := sqlbase.NewImmutableTableDescriptor(*desc.TableDesc())
   132  	if err != nil {
   133  		return err
   134  	}
   135  	v := &roachpb.Value{RawBytes: typed.Value}
   136  	return row.NewUniquenessConstraintViolationError(ctx, immutable, typed.Key, v)
   137  }
   138  
   139  func (ib *indexBackfiller) runChunk(
   140  	tctx context.Context,
   141  	mutations []sqlbase.DescriptorMutation,
   142  	sp roachpb.Span,
   143  	chunkSize int64,
   144  	readAsOf hlc.Timestamp,
   145  ) (roachpb.Key, error) {
   146  	knobs := &ib.flowCtx.Cfg.TestingKnobs
   147  	if knobs.RunBeforeBackfillChunk != nil {
   148  		if err := knobs.RunBeforeBackfillChunk(sp); err != nil {
   149  			return nil, err
   150  		}
   151  	}
   152  	if knobs.RunAfterBackfillChunk != nil {
   153  		defer knobs.RunAfterBackfillChunk()
   154  	}
   155  
   156  	ctx, traceSpan := tracing.ChildSpan(tctx, "chunk")
   157  	defer tracing.FinishSpan(traceSpan)
   158  
   159  	var key roachpb.Key
   160  
   161  	start := timeutil.Now()
   162  	var entries []sqlbase.IndexEntry
   163  	if err := ib.flowCtx.Cfg.DB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error {
   164  		txn.SetFixedTimestamp(ctx, readAsOf)
   165  
   166  		// TODO(knz): do KV tracing in DistSQL processors.
   167  		var err error
   168  		entries, key, err = ib.BuildIndexEntriesChunk(ctx, txn, ib.desc, sp, chunkSize, false /*traceKV*/)
   169  		return err
   170  	}); err != nil {
   171  		return nil, err
   172  	}
   173  	prepTime := timeutil.Now().Sub(start)
   174  
   175  	start = timeutil.Now()
   176  	for _, i := range entries {
   177  		if err := ib.adder.Add(ctx, i.Key, i.Value.RawBytes); err != nil {
   178  			return nil, ib.wrapDupError(ctx, err)
   179  		}
   180  	}
   181  	if knobs.RunAfterBackfillChunk != nil {
   182  		if err := ib.adder.Flush(ctx); err != nil {
   183  			return nil, ib.wrapDupError(ctx, err)
   184  		}
   185  	}
   186  	addTime := timeutil.Now().Sub(start)
   187  
   188  	if log.V(3) {
   189  		log.Infof(ctx, "index backfill stats: entries %d, prepare %+v, add-sst %+v",
   190  			len(entries), prepTime, addTime)
   191  	}
   192  	return key, nil
   193  }