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 }