From 1ad8ea0f65b111b2ffbef574316cee87b4d8b922 Mon Sep 17 00:00:00 2001 From: Yevgeniy Miretskiy Date: Mon, 26 Jul 2021 22:02:05 -0400 Subject: [PATCH 1/2] changefeedccl: Use separate budgets for sink and kvfeed. Use separate memory budget accounting for memory used in kvfeed and the memory used by the sink for in-transit messages. We need to use separate budgets because the rate of incoming messages might be very different from the rate of egress messages. As a result, it's possible that we can re-fill a kvfeed buffer faster than we can drain it; and as a result, the sink will not be able to request additional memory for its inflight messages. The follow on PRs will change the sink to support pushback mode, so the above would not be necessary. Release Notes: None --- pkg/ccl/changefeedccl/changefeed_processors.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/ccl/changefeedccl/changefeed_processors.go b/pkg/ccl/changefeedccl/changefeed_processors.go index 2d6a583e327a..284117c8c05b 100644 --- a/pkg/ccl/changefeedccl/changefeed_processors.go +++ b/pkg/ccl/changefeedccl/changefeed_processors.go @@ -241,9 +241,17 @@ func (ca *changeAggregator) Start(ctx context.Context) { kvFeedMemMon.Start(ctx, pool, mon.BoundAccount{}) ca.kvFeedMemMon = kvFeedMemMon + // NB: sink uses pool bound account, and not kvFeedMemMon. + // This is because if we use shared kvFeedMemMon budget, it is possible that that budget + // will be exhausted by kvfeed (e.g. because of a down or slow sink); Then, when sink + // is no longer unavailable, we will proceed with the message, but once it gets to the sink, + // we won't be able to allocate additional memory because more events could have been added + // to KVFeed buffer. Basically, the problem is that the ingress rate of messages into kvfeed + // buffer is different from the eggress rate from the sink. + // TODO(yevgeniy): The real solution is to have the sink pushback. ca.sink, err = getSink( ctx, ca.flowCtx.Cfg, ca.spec.Feed, timestampOracle, - ca.spec.User(), kvFeedMemMon.MakeBoundAccount(), ca.spec.JobID) + ca.spec.User(), pool.MakeBoundAccount(), ca.spec.JobID) if err != nil { err = changefeedbase.MarkRetryableError(err) From e2f145d33af284fa0c2c48c449d5431ed6605263 Mon Sep 17 00:00:00 2001 From: Yahor Yuzefovich Date: Mon, 26 Jul 2021 17:18:23 -0700 Subject: [PATCH 2/2] colfetcher: limit batches by memory footprint Previously, in the cFetcher we were performing the memory accounting for the output batch at a batch granularity. In some cases this led to batches that significantly exceed the target memory limit. One notable example is the case when we have very wide rows (say large blob column) and an estimated row count - we would allocate the batch based on the estimated row count. Later on we would not realize that each row is large. This commit refactors the memory accounting to be at a row granularity. Whenever a row is finished, we perform the accounting for the last row set. We have to be a bit careful for this accounting to not have significant performance hit, so a new `Allocator.AccountForSet` method is introduced. It assumes that all fixed-length vectors have already been accounted for, handles bytes-like vectors in a special manner (with the help of the caller), and updates the account if there were any decimals or datum-backed values only for the last row. Release note: None --- pkg/col/coldata/batch.go | 21 +++++ pkg/sql/colexec/colbuilder/execplan.go | 51 ++++++----- pkg/sql/colexec/colbuilder/execplan_test.go | 8 +- pkg/sql/colexec/colexecargs/op_creation.go | 11 +++ pkg/sql/colexec/colexecutils/utils.go | 5 ++ pkg/sql/colfetcher/cfetcher.go | 86 +++++++++++-------- .../colfetcher/vectorized_batch_size_test.go | 44 ++++++++++ pkg/sql/colflow/colbatch_scan_test.go | 6 +- pkg/sql/colmem/BUILD.bazel | 1 + pkg/sql/colmem/allocator.go | 46 ++++++++++ .../testdata/logic_test/dist_vectorize | 4 +- .../testdata/logic_test/explain_analyze_plans | 12 +-- .../logic_test/inverted_index_geospatial | 6 +- .../testdata/logic_test/vectorize_local | 6 +- 14 files changed, 229 insertions(+), 78 deletions(-) diff --git a/pkg/col/coldata/batch.go b/pkg/col/coldata/batch.go index 62c65f779982..18e0fc3d421e 100644 --- a/pkg/col/coldata/batch.go +++ b/pkg/col/coldata/batch.go @@ -55,6 +55,9 @@ type Batch interface { // provided Vec. The original and the replacement vectors *must* be of the // same type. ReplaceCol(Vec, int) + // BytesLikeTotalSize returns the total size in bytes of all Bytes-like + // vectors in the batch. + BytesLikeTotalSize() int64 // Reset modifies the caller in-place to have the given length and columns // with the given types. If it's possible, Reset will reuse the existing // columns and allocations, invalidating existing references to the Batch or @@ -181,6 +184,10 @@ func (b *zeroBatch) ReplaceCol(Vec, int) { panic("no columns should be replaced in zero batch") } +func (b *zeroBatch) BytesLikeTotalSize() int64 { + return 0 +} + func (b *zeroBatch) Reset([]*types.T, int, ColumnFactory) { panic("zero batch should not be reset") } @@ -281,6 +288,20 @@ func (m *MemBatch) ReplaceCol(col Vec, colIdx int) { m.b[colIdx] = col } +// BytesLikeTotalSize implements the Batch interface. +func (m *MemBatch) BytesLikeTotalSize() int64 { + var sz int64 + for i, ok := m.bytesVecIdxs.Next(0); ok; i, ok = m.bytesVecIdxs.Next(i + 1) { + switch m.b[i].CanonicalTypeFamily() { + case types.BytesFamily: + sz += m.b[i].Bytes().Size() + case types.JsonFamily: + sz += m.b[i].JSON().Size() + } + } + return sz +} + // Reset implements the Batch interface. func (m *MemBatch) Reset(typs []*types.T, length int, factory ColumnFactory) { cannotReuse := m == nil || m.Capacity() < length || m.Width() < len(typs) diff --git a/pkg/sql/colexec/colbuilder/execplan.go b/pkg/sql/colexec/colbuilder/execplan.go index 218419481dc6..bee3a7853faa 100644 --- a/pkg/sql/colexec/colbuilder/execplan.go +++ b/pkg/sql/colexec/colbuilder/execplan.go @@ -428,15 +428,15 @@ func (r opResult) createDiskBackedSort( // sort itself is responsible for making sure that we stay within // the memory limit. sortUnlimitedAllocator := colmem.NewAllocator( - ctx, r.createBufferingUnlimitedMemAccount( + ctx, r.createUnlimitedMemAccount( ctx, flowCtx, opName+"-sort", processorID, ), factory) mergeUnlimitedAllocator := colmem.NewAllocator( - ctx, r.createBufferingUnlimitedMemAccount( + ctx, r.createUnlimitedMemAccount( ctx, flowCtx, opName+"-merge", processorID, ), factory) outputUnlimitedAllocator := colmem.NewAllocator( - ctx, r.createBufferingUnlimitedMemAccount( + ctx, r.createUnlimitedMemAccount( ctx, flowCtx, opName+"-output", processorID, ), factory) diskAccount := r.createDiskAccount(ctx, flowCtx, opName, processorID) @@ -745,10 +745,17 @@ func NewColOperator( if err := checkNumIn(inputs, 0); err != nil { return r, err } - + // We have to create a separate account in order for the cFetcher to + // be able to precisely track the size of its output batch. This + // memory account is "streaming" in its nature, so we create an + // unlimited one. + cFetcherMemAcc := result.createUnlimitedMemAccount( + ctx, flowCtx, "cfetcher" /* opName */, spec.ProcessorID, + ) estimatedRowCount := spec.EstimatedRowCount scanOp, err := colfetcher.NewColBatchScan( - ctx, streamingAllocator, flowCtx, evalCtx, core.TableReader, post, estimatedRowCount, + ctx, colmem.NewAllocator(ctx, cFetcherMemAcc, factory), flowCtx, + evalCtx, core.TableReader, post, estimatedRowCount, ) if err != nil { return r, err @@ -846,7 +853,7 @@ func NewColOperator( // The disk spilling is disabled by the cluster setting, so // we give an unlimited memory account to the in-memory // hash aggregator and don't set up the disk spiller. - hashAggregatorUnlimitedMemAccount := result.createBufferingUnlimitedMemAccount( + hashAggregatorUnlimitedMemAccount := result.createUnlimitedMemAccount( ctx, flowCtx, opName, spec.ProcessorID, ) newAggArgs.Allocator = colmem.NewAllocator( @@ -869,7 +876,7 @@ func NewColOperator( // We need to create a separate memory account for the // spilling queue because it looks at how much memory it has // already used in order to decide when to spill to disk. - spillingQueueMemAccount := result.createBufferingUnlimitedMemAccount( + spillingQueueMemAccount := result.createUnlimitedMemAccount( ctx, flowCtx, spillingQueueMemMonitorName, spec.ProcessorID, ) spillingQueueCfg := args.DiskQueueCfg @@ -893,7 +900,7 @@ func NewColOperator( return r, err } ehaOpName := "external-hash-aggregator" - ehaMemAccount := result.createBufferingUnlimitedMemAccount(ctx, flowCtx, ehaOpName, spec.ProcessorID) + ehaMemAccount := result.createUnlimitedMemAccount(ctx, flowCtx, ehaOpName, spec.ProcessorID) // Note that we will use an unlimited memory account here // even for the in-memory hash aggregator since it is easier // to do so than to try to replace the memory account if the @@ -967,7 +974,7 @@ func NewColOperator( distinctMemMonitorName, func(input colexecop.Operator) colexecop.Operator { unlimitedAllocator := colmem.NewAllocator( - ctx, result.createBufferingUnlimitedMemAccount(ctx, flowCtx, edOpName, spec.ProcessorID), factory, + ctx, result.createUnlimitedMemAccount(ctx, flowCtx, edOpName, spec.ProcessorID), factory, ) return colexec.NewExternalDistinct( unlimitedAllocator, @@ -1007,7 +1014,7 @@ func NewColOperator( // We are performing a cross-join, so we need to plan a // specialized operator. opName := "cross-joiner" - crossJoinerMemAccount := result.createBufferingUnlimitedMemAccount(ctx, flowCtx, opName, spec.ProcessorID) + crossJoinerMemAccount := result.createUnlimitedMemAccount(ctx, flowCtx, opName, spec.ProcessorID) crossJoinerDiskAcc := result.createDiskAccount(ctx, flowCtx, opName, spec.ProcessorID) unlimitedAllocator := colmem.NewAllocator(ctx, crossJoinerMemAccount, factory) result.Root = colexecjoin.NewCrossJoiner( @@ -1034,7 +1041,7 @@ func NewColOperator( ctx, flowCtx, opName, spec.ProcessorID, ) hashJoinerUnlimitedAllocator = colmem.NewAllocator( - ctx, result.createBufferingUnlimitedMemAccount(ctx, flowCtx, opName, spec.ProcessorID), factory, + ctx, result.createUnlimitedMemAccount(ctx, flowCtx, opName, spec.ProcessorID), factory, ) } hjSpec := colexecjoin.MakeHashJoinerSpec( @@ -1064,7 +1071,7 @@ func NewColOperator( hashJoinerMemMonitorName, func(inputOne, inputTwo colexecop.Operator) colexecop.Operator { unlimitedAllocator := colmem.NewAllocator( - ctx, result.createBufferingUnlimitedMemAccount(ctx, flowCtx, opName, spec.ProcessorID), factory, + ctx, result.createUnlimitedMemAccount(ctx, flowCtx, opName, spec.ProcessorID), factory, ) ehj := colexec.NewExternalHashJoiner( unlimitedAllocator, @@ -1120,7 +1127,7 @@ func NewColOperator( // joiner itself is responsible for making sure that we stay within // the memory limit, and it will fall back to disk if necessary. unlimitedAllocator := colmem.NewAllocator( - ctx, result.createBufferingUnlimitedMemAccount( + ctx, result.createUnlimitedMemAccount( ctx, flowCtx, opName, spec.ProcessorID, ), factory) diskAccount := result.createDiskAccount(ctx, flowCtx, opName, spec.ProcessorID) @@ -1650,15 +1657,17 @@ func (r opResult) createMemAccountForSpillStrategyWithLimit( return &bufferingMemAccount, monitorName } -// createBufferingUnlimitedMemAccount instantiates an unlimited memory monitor -// and a memory account to be used with a buffering disk-backed Operator. The -// receiver is updated to have references to both objects. Note that the -// returned account is only "unlimited" in that it does not have a hard limit -// that it enforces, but a limit might be enforced by a root monitor. +// createUnlimitedMemAccount instantiates an unlimited memory monitor +// and a memory account to be used with a buffering disk-backed Operator (or in +// special circumstances in place of a streaming account when the precise memory +// usage is needed by an operator). The receiver is updated to have references +// to both objects. Note that the returned account is only "unlimited" in that +// it does not have a hard limit that it enforces, but a limit might be enforced +// by a root monitor. // // Note that the memory monitor name is not returned (unlike above) because no // caller actually needs it. -func (r opResult) createBufferingUnlimitedMemAccount( +func (r opResult) createUnlimitedMemAccount( ctx context.Context, flowCtx *execinfra.FlowCtx, opName string, processorID int32, ) *mon.BoundAccount { monitorName := r.getMemMonitorName(opName, processorID, "unlimited" /* suffix */) @@ -1710,10 +1719,10 @@ func (r opResult) finishBufferedWindowerArgs( needsBuffer bool, ) { args.DiskAcc = r.createDiskAccount(ctx, flowCtx, opName, processorID) - mainAcc := r.createBufferingUnlimitedMemAccount(ctx, flowCtx, opName, processorID) + mainAcc := r.createUnlimitedMemAccount(ctx, flowCtx, opName, processorID) args.MainAllocator = colmem.NewAllocator(ctx, mainAcc, factory) if needsBuffer { - bufferAcc := r.createBufferingUnlimitedMemAccount(ctx, flowCtx, opName, processorID) + bufferAcc := r.createUnlimitedMemAccount(ctx, flowCtx, opName, processorID) args.BufferAllocator = colmem.NewAllocator(ctx, bufferAcc, factory) } } diff --git a/pkg/sql/colexec/colbuilder/execplan_test.go b/pkg/sql/colexec/colbuilder/execplan_test.go index 930878fdbb3b..fb25674a9a4b 100644 --- a/pkg/sql/colexec/colbuilder/execplan_test.go +++ b/pkg/sql/colexec/colbuilder/execplan_test.go @@ -103,8 +103,9 @@ func TestNewColOperatorExpectedTypeSchema(t *testing.T) { }, StreamingMemAccount: &streamingMemAcc, } - r, err := NewColOperator(ctx, flowCtx, args) + r1, err := NewColOperator(ctx, flowCtx, args) require.NoError(t, err) + defer r1.TestCleanup() args = &colexecargs.NewColOperatorArgs{ Spec: &execinfrapb.ProcessorSpec{ @@ -113,11 +114,12 @@ func TestNewColOperatorExpectedTypeSchema(t *testing.T) { Post: execinfrapb.PostProcessSpec{RenderExprs: []execinfrapb.Expression{{Expr: "@1 - 1"}}}, ResultTypes: []*types.T{types.Int}, }, - Inputs: []colexecargs.OpWithMetaInfo{{Root: r.Root}}, + Inputs: []colexecargs.OpWithMetaInfo{{Root: r1.Root}}, StreamingMemAccount: &streamingMemAcc, } - r, err = NewColOperator(ctx, flowCtx, args) + r, err := NewColOperator(ctx, flowCtx, args) require.NoError(t, err) + defer r.TestCleanup() m := colexec.NewMaterializer( flowCtx, diff --git a/pkg/sql/colexec/colexecargs/op_creation.go b/pkg/sql/colexec/colexecargs/op_creation.go index 60db4c261793..59812cd807a1 100644 --- a/pkg/sql/colexec/colexecargs/op_creation.go +++ b/pkg/sql/colexec/colexecargs/op_creation.go @@ -131,6 +131,17 @@ func (r *NewColOperatorResult) AssertInvariants() { } } +// TestCleanup releases the resources associated with this result. It should +// only be used in tests. +func (r *NewColOperatorResult) TestCleanup() { + for _, acc := range r.OpAccounts { + acc.Close(context.Background()) + } + for _, m := range r.OpMonitors { + m.Stop(context.Background()) + } +} + var newColOperatorResultPool = sync.Pool{ New: func() interface{} { return &NewColOperatorResult{} diff --git a/pkg/sql/colexec/colexecutils/utils.go b/pkg/sql/colexec/colexecutils/utils.go index c97f34e8e100..e5a780af9be6 100644 --- a/pkg/sql/colexec/colexecutils/utils.go +++ b/pkg/sql/colexec/colexecutils/utils.go @@ -175,6 +175,11 @@ func (b *AppendOnlyBufferedBatch) ReplaceCol(coldata.Vec, int) { colexecerror.InternalError(errors.AssertionFailedf("ReplaceCol is prohibited on AppendOnlyBufferedBatch")) } +// BytesLikeTotalSize implements the coldata.Batch interface. +func (b *AppendOnlyBufferedBatch) BytesLikeTotalSize() int64 { + return b.batch.BytesLikeTotalSize() +} + // Reset implements the coldata.Batch interface. func (b *AppendOnlyBufferedBatch) Reset([]*types.T, int, coldata.ColumnFactory) { colexecerror.InternalError(errors.AssertionFailedf("Reset is prohibited on AppendOnlyBufferedBatch")) diff --git a/pkg/sql/colfetcher/cfetcher.go b/pkg/sql/colfetcher/cfetcher.go index a695c7923fad..7b2a83923797 100644 --- a/pkg/sql/colfetcher/cfetcher.go +++ b/pkg/sql/colfetcher/cfetcher.go @@ -213,7 +213,7 @@ const noOutputColumn = -1 // err := rf.StartScan(..) // // Handle err // for { -// res, err := rf.nextBatch() +// res, err := rf.NextBatch() // // Handle err // if res.colBatch.Length() == 0 { // // Done @@ -313,18 +313,29 @@ type cFetcher struct { allocator *colmem.Allocator memoryLimit int64 - // adapter is a utility struct that helps with memory accounting. - adapter struct { - ctx context.Context - batch coldata.Batch - err error + memAccounting struct { + // varLengthVecIdxs stores the indices into colvecs of those vectors the + // elements of which can be of variable length and which are needed for + // the output. + varLengthVecIdxs []int + // prevBytesLikeTotalSize track the total size of the bytes-like vectors + // that we have already accounted for. + prevBytesLikeTotalSize int64 + // maxCapacity if non-zero indicates the target capacity of the output + // batch. It is set when at the row finalization we realize that the + // output batch has exceeded the memory limit. + maxCapacity int } } -func (rf *cFetcher) resetBatch(timestampOutputIdx, tableOidOutputIdx int) { +func (rf *cFetcher) resetBatch() { var reallocated bool var minCapacity int - if rf.machine.limitHint > 0 && (rf.estimatedRowCount == 0 || uint64(rf.machine.limitHint) < rf.estimatedRowCount) { + if rf.memAccounting.maxCapacity > 0 { + // If we have already exceeded the memory limit for the output batch, we + // will only be using the same batch from now on. + minCapacity = rf.memAccounting.maxCapacity + } else if rf.machine.limitHint > 0 && (rf.estimatedRowCount == 0 || uint64(rf.machine.limitHint) < rf.estimatedRowCount) { // If we have a limit hint, and either // 1) we don't have an estimate, or // 2) we have a soft limit, @@ -351,15 +362,16 @@ func (rf *cFetcher) resetBatch(timestampOutputIdx, tableOidOutputIdx int) { if reallocated { rf.machine.colvecs = rf.machine.batch.ColVecs() // Pull out any requested system column output vecs. - if timestampOutputIdx != noOutputColumn { - rf.machine.timestampCol = rf.machine.colvecs[timestampOutputIdx].Decimal() + if rf.table.timestampOutputIdx != noOutputColumn { + rf.machine.timestampCol = rf.machine.colvecs[rf.table.timestampOutputIdx].Decimal() } - if tableOidOutputIdx != noOutputColumn { - rf.machine.tableoidCol = rf.machine.colvecs[tableOidOutputIdx].Datum() + if rf.table.oidOutputIdx != noOutputColumn { + rf.machine.tableoidCol = rf.machine.colvecs[rf.table.oidOutputIdx].Datum() } // Change the allocation size to be the same as the capacity of the // batch we allocated above. rf.table.da.AllocSize = rf.machine.batch.Capacity() + rf.memAccounting.prevBytesLikeTotalSize = rf.machine.batch.BytesLikeTotalSize() } } @@ -430,6 +442,7 @@ func (rf *cFetcher) Init( //gcassert:bce typs[i] = colDescriptors[i].GetType() } + rf.memAccounting.varLengthVecIdxs = colmem.GetVarLengthIdxs(rf.typs) var err error @@ -455,6 +468,7 @@ func (rf *cFetcher) Init( switch colinfo.GetSystemColumnKindFromColumnID(col) { case descpb.SystemColumnKind_MVCCTIMESTAMP: table.timestampOutputIdx = idx + rf.memAccounting.varLengthVecIdxs = append(rf.memAccounting.varLengthVecIdxs, idx) rf.mvccDecodeStrategy = row.MVCCDecodingRequired case descpb.SystemColumnKind_TABLEOID: table.oidOutputIdx = idx @@ -700,7 +714,7 @@ func (rf *cFetcher) StartScan( return nil } -// fetcherState is the state enum for nextBatch. +// fetcherState is the state enum for NextBatch. type fetcherState int //go:generate stringer -type=fetcherState @@ -776,7 +790,7 @@ const ( // stateFinished. stateEmitLastBatch - // stateFinished is the end state of the state machine - it causes nextBatch + // stateFinished is the end state of the state machine - it causes NextBatch // to return empty batches forever. stateFinished ) @@ -784,20 +798,6 @@ const ( // Turn this on to enable super verbose logging of the fetcher state machine. const debugState = false -// NextBatch is nextBatch with the addition of memory accounting. -func (rf *cFetcher) NextBatch(ctx context.Context) (coldata.Batch, error) { - rf.adapter.ctx = ctx - rf.allocator.PerformOperation( - rf.machine.colvecs, - rf.nextAdapter, - ) - return rf.adapter.batch, rf.adapter.err -} - -func (rf *cFetcher) nextAdapter() { - rf.adapter.batch, rf.adapter.err = rf.nextBatch(rf.adapter.ctx) -} - // setNextKV sets the next KV to process to the input KV. needsCopy, if true, // causes the input kv to be deep copied. needsCopy should be set to true if // the input KV is pointing to the last KV of a batch, so that the batch can @@ -821,13 +821,14 @@ func (rf *cFetcher) setNextKV(kv roachpb.KeyValue, needsCopy bool) { rf.machine.nextKV = kvCopy } -// nextBatch processes keys until we complete one batch of rows, -// coldata.BatchSize() in length, which are returned in columnar format as a -// coldata.Batch. The batch contains one Vec per table column, regardless of -// the index used; columns that are not needed (as per neededCols) are empty. -// The Batch should not be modified and is only valid until the next call. -// When there are no more rows, the Batch.Length is 0. -func (rf *cFetcher) nextBatch(ctx context.Context) (coldata.Batch, error) { +// NextBatch processes keys until we complete one batch of rows (subject to the +// limit hint and the memory limit while being max coldata.BatchSize() in +// length), which are returned in columnar format as a coldata.Batch. The batch +// contains one Vec per table column, regardless of the index used; columns that +// are not needed (as per neededCols) are filled with nulls. The Batch should +// not be modified and is only valid until the next call. When there are no more +// rows, the Batch.Length is 0. +func (rf *cFetcher) NextBatch(ctx context.Context) (coldata.Batch, error) { for { if debugState { log.Infof(ctx, "State %s", rf.machine.state[0]) @@ -870,7 +871,7 @@ func (rf *cFetcher) nextBatch(ctx context.Context) (coldata.Batch, error) { rf.machine.state[0] = stateDecodeFirstKVOfRow case stateResetBatch: - rf.resetBatch(rf.table.timestampOutputIdx, rf.table.oidOutputIdx) + rf.resetBatch() rf.shiftState() case stateDecodeFirstKVOfRow: // Reset MVCC metadata for the table, since this is the first KV of a row. @@ -1119,17 +1120,26 @@ func (rf *cFetcher) nextBatch(ctx context.Context) (coldata.Batch, error) { rf.machine.tableoidCol.Set(rf.machine.rowIdx, tree.NewDOid(tree.DInt(rf.table.desc.GetID()))) } - // We're finished with a row. Bump the row index, fill the row in with - // nulls if necessary, emit the batch if necessary, and move to the next + // We're finished with a row. Fill the row in with nulls if + // necessary, perform the memory accounting for the row, bump the + // row index, emit the batch if necessary, and move to the next // state. if err := rf.fillNulls(); err != nil { return nil, err } + rf.memAccounting.prevBytesLikeTotalSize = rf.allocator.AccountForSet( + rf.machine.batch, rf.memAccounting.varLengthVecIdxs, + rf.machine.rowIdx, rf.memAccounting.prevBytesLikeTotalSize, + ) rf.machine.rowIdx++ rf.shiftState() var emitBatch bool + if rf.memAccounting.maxCapacity == 0 && rf.allocator.Used() >= rf.memoryLimit { + rf.memAccounting.maxCapacity = rf.machine.rowIdx + } if rf.machine.rowIdx >= rf.machine.batch.Capacity() || + (rf.memAccounting.maxCapacity > 0 && rf.machine.rowIdx >= rf.memAccounting.maxCapacity) || (rf.machine.limitHint > 0 && rf.machine.rowIdx >= rf.machine.limitHint) { // We either // 1. have no more room in our batch, so output it immediately diff --git a/pkg/sql/colfetcher/vectorized_batch_size_test.go b/pkg/sql/colfetcher/vectorized_batch_size_test.go index b6dfdc010e71..073175279991 100644 --- a/pkg/sql/colfetcher/vectorized_batch_size_test.go +++ b/pkg/sql/colfetcher/vectorized_batch_size_test.go @@ -122,3 +122,47 @@ CREATE TABLE t (a PRIMARY KEY, b) AS SELECT i, i FROM generate_series(1, 511) AS }) } } + +// TestCFetcherLimitsOutputBatch verifies that cFetcher limits its output batch +// based on the memory footprint. +func TestCFetcherLimitsOutputBatch(t *testing.T) { + defer leaktest.AfterTest(t)() + defer log.Scope(t).Close(t) + skip.UnderMetamorphic(t, "This test doesn't work with metamorphic batch sizes.") + + tc := testcluster.StartTestCluster(t, 1, base.TestClusterArgs{ReplicationMode: base.ReplicationAuto}) + ctx := context.Background() + defer tc.Stopper().Stop(ctx) + conn := tc.Conns[0] + + // We set up a table with 50 rows that take up 16KiB each and we lower the + // distsql_workmem session variable to 128KiB. We also collect the stats on + // the table so that we had an estimated row count of 50 for the scan. With + // such setup the cFetcher will allocate an output batch of capacity 50, yet + // after setting the 7th or so row the footprint of the batch will exceed + // the memory limit. As a result, we will get around 7 batches. + _, err := conn.ExecContext(ctx, ` +SET distsql_workmem='128KiB'; +CREATE TABLE t (a PRIMARY KEY, b) AS SELECT i, repeat('a', 16 * 1024) FROM generate_series(1, 50) AS g(i); +ANALYZE t +`) + assert.NoError(t, err) + + batchCountRegex := regexp.MustCompile(`vectorized batch count: (\d+)`) + rows, err := conn.QueryContext(ctx, `EXPLAIN ANALYZE (VERBOSE, DISTSQL) SELECT * FROM t`) + assert.NoError(t, err) + foundBatches := -1 + for rows.Next() { + var res string + assert.NoError(t, rows.Scan(&res)) + if matches := batchCountRegex.FindStringSubmatch(res); len(matches) > 0 { + foundBatches, err = strconv.Atoi(matches[1]) + assert.NoError(t, err) + } + } + + // There is a bit of non-determinism (namely, in how data in coldata.Bytes + // is appended), so we require that we get at least 7 batches. If we get + // more, that's still ok since it means that the batches were even smaller. + assert.GreaterOrEqual(t, foundBatches, 7) +} diff --git a/pkg/sql/colflow/colbatch_scan_test.go b/pkg/sql/colflow/colbatch_scan_test.go index f8d02afe456f..6f3e8e7e2a05 100644 --- a/pkg/sql/colflow/colbatch_scan_test.go +++ b/pkg/sql/colflow/colbatch_scan_test.go @@ -90,6 +90,7 @@ func TestColBatchScanMeta(t *testing.T) { if err != nil { t.Fatal(err) } + defer res.TestCleanup() tr := res.Root tr.Init(ctx) meta := tr.(*colexecutils.CancelChecker).Input.(colexecop.DrainableOperator).DrainMeta() @@ -150,7 +151,6 @@ func BenchmarkColBatchScan(b *testing.B) { b.SetBytes(int64(numRows * numCols * 8)) b.ResetTimer() for i := 0; i < b.N; i++ { - b.StopTimer() args := &colexecargs.NewColOperatorArgs{ Spec: &spec, StreamingMemAccount: testMemAcc, @@ -160,14 +160,16 @@ func BenchmarkColBatchScan(b *testing.B) { b.Fatal(err) } tr := res.Root - tr.Init(ctx) b.StartTimer() + tr.Init(ctx) for { bat := tr.Next() if bat.Length() == 0 { break } } + b.StopTimer() + res.TestCleanup() } }) } diff --git a/pkg/sql/colmem/BUILD.bazel b/pkg/sql/colmem/BUILD.bazel index 7fb88a15235b..a4305050971c 100644 --- a/pkg/sql/colmem/BUILD.bazel +++ b/pkg/sql/colmem/BUILD.bazel @@ -7,6 +7,7 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/col/coldata", + "//pkg/col/coldataext", "//pkg/col/typeconv", "//pkg/sql/colexecerror", "//pkg/sql/memsize", diff --git a/pkg/sql/colmem/allocator.go b/pkg/sql/colmem/allocator.go index 2eeaf4d0b260..c6ef550389f3 100644 --- a/pkg/sql/colmem/allocator.go +++ b/pkg/sql/colmem/allocator.go @@ -14,6 +14,7 @@ import ( "context" "github.com/cockroachdb/cockroach/pkg/col/coldata" + "github.com/cockroachdb/cockroach/pkg/col/coldataext" "github.com/cockroachdb/cockroach/pkg/col/typeconv" "github.com/cockroachdb/cockroach/pkg/sql/colexecerror" "github.com/cockroachdb/cockroach/pkg/sql/memsize" @@ -336,6 +337,33 @@ func (a *Allocator) PerformAppend(batch coldata.Batch, operation func()) { a.AdjustMemoryUsage(after - before) } +// AccountForSet accounts for the variable length memory allocated for all +// elements of rowIdx row that has just been set in batch. It assumes that batch +// has been instantiated via this allocator (meaning that all fixed-length +// vectors are already properly accounted for). It returns the total memory +// footprint of all Bytes-like vectors in batch. +func (a *Allocator) AccountForSet( + batch coldata.Batch, varLengthVecIdxs []int, rowIdx int, prevBytesLikeTotalSize int64, +) (newBytesLikeTotalSize int64) { + var extraDatumsSize int64 + for _, vecIdx := range varLengthVecIdxs { + vec := batch.ColVec(vecIdx) + switch vec.CanonicalTypeFamily() { + case types.BytesFamily: + newBytesLikeTotalSize += vec.Bytes().Size() + case types.JsonFamily: + newBytesLikeTotalSize += vec.JSON().Size() + case types.DecimalFamily: + d := vec.Decimal().Get(rowIdx) + extraDatumsSize += int64(tree.SizeOfDecimal(&d)) + case typeconv.DatumVecCanonicalTypeFamily: + extraDatumsSize += int64(vec.Datum().Get(rowIdx).(*coldataext.Datum).Size()) + } + } + a.AdjustMemoryUsage(newBytesLikeTotalSize - prevBytesLikeTotalSize + extraDatumsSize) + return newBytesLikeTotalSize +} + // Used returns the number of bytes currently allocated through this allocator. func (a *Allocator) Used() int64 { return a.acc.Used() @@ -476,3 +504,21 @@ func EstimateBatchSizeBytes(vecTypes []*types.T, batchLength int) int64 { bytesVectorsSize += int64(numBytesVectors+numUUIDVectors) * memsize.Int32 * int64(batchLength+1) return acc*int64(batchLength) + bytesVectorsSize } + +// GetVarLengthIdxs returns indices into typs for which each element can take up +// variable amount of space. +func GetVarLengthIdxs(typs []*types.T) []int { + var varLengthIdxs []int + for i, typ := range typs { + switch typeconv.TypeFamilyToCanonicalTypeFamily(typ.Family()) { + case types.BytesFamily, types.JsonFamily, types.DecimalFamily: + varLengthIdxs = append(varLengthIdxs, i) + case typeconv.DatumVecCanonicalTypeFamily: + _, isVarlen := tree.DatumTypeSize(typ) + if isVarlen { + varLengthIdxs = append(varLengthIdxs, i) + } + } + } + return varLengthIdxs +} diff --git a/pkg/sql/logictest/testdata/logic_test/dist_vectorize b/pkg/sql/logictest/testdata/logic_test/dist_vectorize index bf09c6a47abb..2cb30931c936 100644 --- a/pkg/sql/logictest/testdata/logic_test/dist_vectorize +++ b/pkg/sql/logictest/testdata/logic_test/dist_vectorize @@ -77,7 +77,7 @@ regions: table: kv@primary spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzsVd1u00wQvf-eYjVX7aeN_Js29VWhKlIFTVCSwgWKqq09MlacXbO7ThqiPBYvwJMh2zHESbGNEAoRvdwZH8-cc2Z3VqA-xeDB6PrN9dWY-CLl-uT_U_JqOLgl0zlQ4CLAPpuhAu8DWEDBBgoOUHCBQhcmFBIpfFRKyOyTVQ64CR7BMylEPEl1Fp5Q8IVE8FagIx0jeDBmDzEOkQUoDRMoBKhZFOdlpvPLREYzJpdAYZQwrjzSMbLCg1R7pC84AoXX74iOZugR8-sXVZx9wTVyHQm-l5JioYhEFnjEKiIPS41lqEdeAoUHpv2PqIhIdZIVytrKcWXAgsmaQnHa0FKahQietabtqb8IQ4kh00Ia3Srzq8Fdf3w_HLwfnZwCBXxEP92n8xt92j_t80d7KRcyQIlBpbfJup6JtWPi6O72_qY_Prm0_gwTp8LEaj9sVvOwGXbHcI5n3BrIb5l0dtBxs9ubZLcwyekY7vGY1EB-y6Tzg5rktDfJaWGS28nfuCMxqYH8lkm9g5rktjfJbWFSt3M8FjVQ37Lo4q_ZrU_0OUSVCK5wZ8c-_Wcz270YhFgsaiVS6eNbKfy8THEc5Lg8EKDSRdYqDje8SGUNboOtWrBdAVu7YLu-ckNppxbt1oPdX-k7VzEXFDjqhZBTEjON3F9-N72ML1ikq-MQoEIZsTj6zPZnpYRt5t_HaI6bO1CmyotQ5orLUGZnqBQLKx-YrWewKkm3VpKzej3PnvXcleS8VpJevZ69Zz13Jbmofy3Mhoeq_pn7NxSdrP_7FgAA__9xHjpe +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzsls9u004Qx--_p1jNqf1pI_9Nm_pUqIpUQROUpHBAUbW1R8aqvWt2121ClMfiBXgyZDuGOCm2EUJBoced8ezMfL6zu16C-hSDB5PLN5cXU-KLjOuj_4_Jq_Homtw_AAUuAhyyBBV4H8ACCjZQcICCCxT6MKOQSuGjUkLmnyyLgKtgDp5JIeJppnPzjIIvJIK3BB3pGMGDKbuLcYwsQGmYQCFAzaK4SHP_cJ7KKGFyARQmKePKIz0jTzzKtEeGgiNQeP2O6ChBj5hfv6hy7QuuketI8B2XFI-KSGSBR6zScrfQWJkG5CVQSNicJJgIuSAsjoXPNAYeMQvfHdP-R1REZDrNi8hLLvasDBbMVhTK1bplpVmI4Fkr2h3LizCUGDItpNGvU7kY3Qynt-PR-8nRMVDAOfrZbqu_Uaf90zp_lJdxIQOUGNRqm62aO7G2BJ7cXN9eDadH59af6cSpdWJ1H0SrfRANu2c4hzGKLWA2BDzZ6yja3QW0Owjo9Az3MARsAbMh4OleBXS6C-h0ENDtFXfjAQjYAmZDwMFeBXS7C-h2ELDfOwz5WrBsyHf217zlT9Q5RpUKrnDrTX96ZzN_6zEIsfwxUCKTPr6Vwi_SlMtREVcYAlS69Frl4oqXrrzAzWCrMdiuBVvbwXZz5pbUTmO02xzs_krdBcUCKHDUj0Lek5hp5P7iu-iV_ZFFuj4OASqUEYujz2x3Vqqw9dnwMXrA9fmoXNUhqXzlQam8CSrFwtoHZucZrCPpNyI5aeZ58sxzG8lpI5JBM8_BM89tJGfNt4XZclE1X3P_BtHZ6r9vAQAA__-opWgS query T EXPLAIN ANALYZE (DISTSQL) SELECT * FROM kv JOIN kw ON kv.k = kw.k @@ -123,7 +123,7 @@ regions: table: kw@primary spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzsmt1u2zYUx-_3FMS52la5MiU7TQQUMDZ0QLo1HtJiN4MvGOnMFiyLLknH8YI81l5gTzbImtv6Q19GG1Km7yLRlA5_-p-jv5jzCPJjAgG8f_Pbm58_kB_JL7fDd2R6T94Or2_IdEmGN2R6_3JKXpPp8uUUHEh5hDdshhKCP4GCAx444IMDPXCgDyMH5oKHKCUX2U8e1xOuowcIug7E6XyhstMjB0IuEIJHULFKEAL4wO4SvEUWoXC74ECEisXJ-jbT-8FcxDMmVuDA-zlLZUA6bnbjX_8gKp5hQLr__iPz45CnClMV83RvSPClJAJZFBCan7lbKdycuiQ_gQN3TIUTlIQv1HyhApKFsp63OUFh9ORAfpSvcLOCuxWZMDnZjn2Q_X7kgFRsjBDQJ-c4JBc7SJb7SFzaUiheIZTP1-EiQoHR7nVeZDeu9asDfN-hGONbHqcoXLqjuQT_Ut8P6IsfXot4PMn_BAeG2WoH1Bl4zsB3Bpno8QHDxT7aGXsgM5xxsSIsSXjIFEYB6a55ZmPyY0IUzuYkiuWULCQb42a4Me7PKP0aKBfpIUwHCd3wDp-7tL_NpmDFlWH3C8PubYVN66cFra4Urtdx_TamBT0WyqsataKtULxCKM9YK-gJ1gqvvr68Gknnd9xeG_VFj4VyWSPp2grFK4TyjEnnnWDS-fX15ddIul7H7bdRX_RYKFc1kq6tULxCKM-YdP4JJl2vvr56NZKu32mjuuixSPrVKddxKWFpRCjhaoKijXi8QjzPmHy9E0y-ii2PW5Rznkrc-TQ9fOVuRhCjMebPRfKFCPF3wcP1bfLD4Xre-kshQqnyUS8_uE43Q1IxVfZp-y3JdXO91I_-ojD6FNWSiylJmMI0XH0Kf3N-yWK1vbAIJYqYJfHfbH_Vm2n_52OI8f162V8MbRLz09h6zZvRGcoMxe7kr4_kSjMSWoLk8qsgoU2R0GKRWysT2reRCW1QCz3jamF59BeF0Vv7QK80I9FSC8uR0GKRWyuTnVpoCRNvl0n3Syb-9uthd7JfOplu16KucZW0d6QnPmE5lCMpNtpteKC6PbGBD9ROT1zBRLcn1uIX-kd64hOWSTmSYqNtRi0sj163JzbwgdrpiSuY6PbEWmrhRRNPbAeSV2er3AyJlXvS5UiK_bcZb8zy6LVbZQPzXrtV1qLyy7NVbobEyj3pciTF_tuMWlgevXarrKUWVjDRbZW1qPzqbJX3_stwbKvFCcukgolus2yiTqzcra5gUuLBzXhtVsVvpV-mx_Zb2MtEt2PWUxDNbuMwUSclRtyQgnjuuTgApVHThSXJv9dLYpRrNpGJbtesJ3fKmdjpmsuZaN-5NhJKsRU35M3ZpDvNFofYpD3NFjPRpOntzMSI7WsjoRRbcUMK4l6rioWuefT03X8BAAD__55xcPI= +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzsmt1u2zYUx-_3FMS52la5MiU7TQQUMDZ0QLo1HtJiN4MvGOnMFiyLLknH8YI81l5gTzbImtv6Q5_oQk70XSSa0uFP53_0F3MeQX5MIID3b3558-MH8j356Xb8jszvydvx9Q2Zr8n4hszvX87JazJfv5yDAymP8IYtUELwO1BwwAMHfHBgAA4MYeLAUvAQpeQi-8njdsJ19ABB34E4Xa5UdnriQMgFQvAIKlYJQgAf2F2Ct8giFG4fHIhQsTjZ3mZ-P1qKeMHEBhx4v2SpDEjPzW78829ExQsMSP_vv2R-HPJUYapinh4NCb6WRCCLAkLzM3cbhbtTl-QHcGDBHsgCF1xsCEsSHjKFUUD627E7psIZSsJXarlSAcnC3F5zd4LC5MmB_Chf_W51dxsyY3K2v65R9vuJA1KxKUJAn5x2uC4OcK2Pcbm0g8C8QmCfr8NFhAKjw-u8yG5c61cn2L9DMcW3PE5RuPQgVxP8Q307oi--ey3i6Sz_ExwYZ6sdUWfkOSPfGWViwQcMV8fYy3hmY_JjQhQuliSK5ZysJJtia9yfUfo1UK7SU5hOErrhPb506XCfTcGKK8MeFoY92Aub1pcMra4wrtdz_a5JhrYF9qpGjekiMK8Q2DPWGNrBGuPVzz2vhlj9njvoWu7RtsAua4i1i8C8QmDPKFavg2L16-eeX0Osg5477Fru0bbArmqItYvAvEJgzyhWv4NiHdTPvUENsQ57Xcs82hbXsFqqPZcSlkaEEq5mKLqGzitE94yiHXRQtBXbPbcolzyVePDpffrK_YwgRlPMn4vkKxHir4KH29vkh-PtvO0XTYRS5aNefnCd7oakYqrs0_2_JNfP86V-9BeF0aeo1lzMScIUpuHmU_i782sWq_2FRShRxCyJ_2THq95N-1erIcb322V_MbQT7aex7Zp3owuUGYrDyV8fyZVmJLQEyeVXQUKbIqHFSW5tmtChjUxog1roGVcLy6O_KIze2gd6pRmJllpYjoQWJ7m1aXJQCy1h4h0y6X_JxN9_PRxO9ksn0_1a1Deukg5aeuIOp0M5kmKj_X94oLo9sYEP1E5PXMFEtyfW4heGLT1xh9OkHEmx0TajFpZHr9sTG_hA7fTEFUx0e2IttfCiiSe2A8mrs1VuhsTKPelyJMX-24w3Znn02q2ygbrXbpW1ZPnl2So3Q2LlnnQ5kmL_bUYtLI9eu1XWUgsrmOi2ylqy_OpslY_-y9C21aLDaVLBRLdZNjFPrNytrmBS4sHNeG1WxW-lX6Zt-y3sZaLbMespiGa3cZiYJyVG3JCCeO65OAGlUdOFJeI_6iUxyjWbyES3a9ajnXImdrrmcibad66NhFJsxQ15czbpTrPFITZpT7PFTDRpejszMWL72kgoxVbckIJ41KpioWuePH3zTwAAAP__FEHMWg== # Verify execution. statement ok diff --git a/pkg/sql/logictest/testdata/logic_test/explain_analyze_plans b/pkg/sql/logictest/testdata/logic_test/explain_analyze_plans index d5cbb6186e6b..21b6e85cd0c9 100644 --- a/pkg/sql/logictest/testdata/logic_test/explain_analyze_plans +++ b/pkg/sql/logictest/testdata/logic_test/explain_analyze_plans @@ -108,7 +108,7 @@ regions: table: kw@primary spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzsm-9u2robx9__rsLyq04LC3ago0iT2Kb9jrqzwtQ_R5qOUOUSHxoBCXNMaU_Vyzo3cK7sKKGsQIidZF3txHnXxDF58vHXX8dPnt7D8PsUduHZpy-fPp6Dyc2biQXIzfhgsnwzeQX-fzo4AZMb8Hlw3AeTJRj040vAOxC1g99OBxdfwYdv8UloQT9waZ_MaAi7f0IELYihBR1owRa0YBsOLThnwYiGYcCiS-7jDsfuLew2Lej58wWPTg8tOAoYhd17yD0-pbALz8nVlJ5S4lJmN6EFXcqJN41vM7npzZk3I-wOWvBsTvywCxp2dOPBgndBLwrj9z8A92a0C5r__hOujkeBz6nPvcBPNLFgGQJGidsFj52v7jhdn-qAD9CCV4SPrmkIggWfR7eJgor7rU8gOHyw4Opo9azrZ7m6A9ckvN5-il50_dCCISdjCrvowSoG53AHzjIJx0alx4NT8Tz9TsBcyqi7-zuvoxtnumoP6RPKxvRz4PmU2WhHh1P6Fz_oodev3jFvfL3684my1YuQ01s6WiShzsgtmNFZwO4AmU6DEeHU7YJmTDJqC79PAaezOXC9cAIWIRnTdXNu0E8QnTwaez8eMzomPGA2aifGxoKDFcdHQb3vf7vsD84v-xdfvhz0UMTh7OLkoIejvz4OLvrnj3-nAPnF8mn9nHzEeHDz5_CcXZxcHkeAnOjolPouZbGCQA_bPecZoT0BaWcAsvD3IdlLox80grmNd3RSNOx2atiHW2Gj7C6J5EuIjRu2U26XREXxvM2wiJQfD07F84KLCKrUIiLR2OYiclitRSS3fCSLCCr7IoKz2w3O4MZOw26V225QUTydDG5cfjw4Fc8LujGulBtLNLbpxm-r5ca55SNxY1x2N3ay242TwY1bDbtdbrtBRfEcZXDj8uPBqXhe0I2dSrmxRGObbtyplhvnlo_EjZ2yu3Eru920Mrhxu1Fus0FF4bTlXtywESC-CxAI-DVl5QaFU0G9oCu3KuXKErVtuvJRtVw5t3wkrtwquytLvoCc0nAe-CHdSX_v_-VmRIu6Y7qiGwYLNqJfWTCKb7M6HMT94tSRS0O-asWrg2N_3RRywkXp8185iZor08gefSc1ep_yZcAmYEo49Ud3P8Jfn18Sj28_mEtDyjwy9f4myaded3s05RH1buLH3mhau_OPtviZ160zGkYodjs_PxLkKGaCBEw6z8IE5WZS6yQ58VXrRAkTlMMMsXZmKI6-kxq9sQO6Y4Yvz0SJGUqY1DqRmaEhTPAuk-Ymk20kzd3OjhBoS6fXyj1TRBw9apq4NkqYtGsmCduodZJkYqROWkIr3UGy27kt7IwPt41Yu7fSw4IJhgrLQYwkfTdahgFVnmDQcETNTDBIJr5qnSjZe70tmGCosEzESNJ3o3qYoTh65QkGDUfUzASDZOKr1okSM-wIX2yPxAmGo4IJhgprTIxEkLXQI-kiCd_IjaOYiZkJBgkTI3WCEl_zRBkGM5YXlOdrnik6yfONsGYiSWjosQWRxa96ULWc_KqzD2qUnvikV6cfJEyM3KxKmAiyGpo4oiR-1YOqxhElk191CkKN0hNfK7fem1FLnIRAiQ97dRZCwsTM4gkZlPQNmh65GUn8ZiYiZFBU77rVQBGXK6hmombprWsg8jIxc9Nal1bkh6J7uYxs8ps5qHUhRF4mZm5a6_qK_FB0r5mRTX4zB1VcDYEk5RCorodIIi1cEGEwFNUbNB2hCNIbmqRn6pqIPf-_VtdEJJnoXROhIxPVmQg1c6dwTYTBUGql5Epv6LEZwXrXRKhxxLomIi8TMzMRMii1UnKlNzRxRHFNBJbUROC6JiKJtK6JyA9F9QZNRyhmFlrIoOhePYPrmojhw_Dhf_8FAAD__2EN7jc= +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzsm99u4jgbxs-_q7B81NGECXagpUgjMTOab9XZFkb9s9JohSqXeGkEJIxjSrtVL2tvYK9slVCmkBA7yXRqN85ZE2N48_Pjx_Hrt_cw_D6FXXj2-fjzp3MwuXk3sQC5Ge9Nlu8mb8D_TwcnYHIDvgyO-mCyBIN-_BHwHkTt4LfTwcVX8PFbfBNa0A9c2iczGsLunxBBC2JoQQdasAUt2IZDC85ZMKJhGLDoI_dxhyP3FnabFvT8-YJHt4cWHAWMwu495B6fUtiF5-RqSk8pcSmzm9CCLuXEm8Y_M7npzZk3I-wOWvBsTvywCxp29MODBe-CXhTG738A7s1oFzT__SdcXY8Cn1Ofe4GfamLBMgSMErcLHjtf3XG6vtUBH6EFZ-QWzOgsYHeATKfBiHDqdkEzbrsifHRNQxAs-DwKIQo4_s71DQSHDxZcXa04rJ_z6g5ck_B6-wl70eeHFgw5GVPYRQ9WOXD7CXDLNDgbVRodzkT39D0BcymjbvJ73kY_nOtTO0bhhLIx_RJ4PmU2Suh3Sv_iez309s175o2vV38-jYDVi4aD3tLRIg1cRDJqC79PAaezOXC9cAIWIRnT0qCfIDpF9PdhPGZ0THjAbNROjY0FByuOj2L70P922R-cX_Yvjo_3eijicHZxstfD0V-fBhf988e_M4D8Yvm0fk4-Yjy4-XN4zi5OLo8iQE50dUp9l7JYQaCH7Z7zjNCegLRzAFn4u5DspNEPGsHcxgmdlA27nRn2_lbYKL-DIvnSY-OG7VTXQVFZdAc5Fp9qo8OZ6F5w8UGVWnwk-ttcfPartfgUlo9k8UGvffHB-a0I53Bxp2G3qmtFqCy6Tg4XrzY6nInuBV0cV8rFJfrbdPGDarl4YflIXBy_dhd38luRk8PFWw27XV0rQmXRHeZw8Wqjw5noXtDFnUq5uER_my7eqZaLF5aPxMWd1-7irfxW1Mrh4u1GdY0IlQXXlnt4w0aA-C5AIODXlFUXIs6E-IJu3qqUm0uUuOnmh9Vy88Lykbh567W7ueSE55SG88APaSK9v_ubmxEt6o7pim4YLNiIfmXBKP6Z1eUg7henuFwa8lUrXl0c-eumkBMuOh74lZOouTKN_NF3MqP3KV8GbAKmhFN_dPcj_PX9JfH49oO5NKTMI1Pvb5J-6nW3R8MeUe8mfuyNprVz_2iLn3ndOqNhhCLZ-fmRIEcxEyRg0nkWJqgwk1on6YmvWidKmKACZoi1M0Nx9J3M6I0d0IQZvjwTJWYoYVLrRGaGhjDBSSbNTSbbSJrJzo4QaEun18odU0QcPWqauDZKmLRrJinbqHWSZmKkTlpCK00gSXZuCzvj_W0j1u6tdL9kgqHCchAjyd6NvoYBVZ5g0HBEzUwwSCa-ap0o2XsdlEwwVFgmYiTZu1E9zFAcvfIEg4YjamaCQTLxVetEiRl2hC-2h-IEw2HJBEOFNSZGIsha6JF0kYRv5MZRzMTMBIOEiZE6QanTPFGGwYzlBRU5zTNFJ0XOCGsmkoSGHlsQWfyqB1XLya86-6BG6akjvTr9IGFi5GZVwkSQ1dDEESXxqx5UNY4omfyqUxBqlJ46rdx6b0YtcRICpQ726iyEhImZxRMyKNkbND1yM5L4zUxEyKCo3nWrgSIuV1DNRM3SW9dAFGVi5qa1Lq0oDkX3chnZ5DdzUOtCiKJMzNy01vUVxaHoXjMjm_xmDqq4GgJJyiFQXQ-RRlq6IMJgKKo3aDpCEaQ3NEnP1DURO_5_ra6JSDPRuyZCRyaqMxFq5k7pmgiDodRKKZTe0GMzgvWuiVDjiHVNRFEmZmYiZFBqpRRKb2jiiOKaCCypicB1TUQaaV0TURyK6g2ajlDMLLSQQdG9egbXNRHDh-HD__4LAAD__xCkSa4= # This query verifies stats collection for the hashJoiner, distinct and sorter. query T @@ -166,7 +166,7 @@ regions: table: kw@primary spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzsm99u27YXx-9_T0HwqsVPrkxKdhwDBYL-GZZui4ckGDAMvlAsLhZsS65Ix8mCPNZeYE82SK7qyLR4pKQLWdF3kRna5Occni_1pXSP-ec5HuKLjz9_fH-JPpxeXJ6evb9Er2brN-vX6Ifz0S9odoM-jU7P0GyNRmdodvNmht6irB2Nzj98PEfvfs-vsIPjJGRnwYJxPPwDE-xgih3sYQf72ME9PHbwMk0mjPMkzf7lPu9wGt7iYdfBUbxciezjsYMnScrw8B6LSMwZHuLL4GrOzlkQstTtYgeHTATRPP-Z2c3JMo0WQXqHHXyxDGI-RB03--HRSgzRSTaMn35DIlqwIer-8zffXE-SWLBYREksNaXJmqOUBeEQfel8dSdY8dEAvcMOvgrEZMo4SlZimf1MNqi8X_EBweMHB2-uNnMt5nJ1h6YBn5ZncZL9_9jBXATXDA_Jg_M0OP0dOGsZjkse46HfIx5aiWf7Pas4SUOWsrD0TeOsJ_Qvexj_GPDppySKWeqSnQScsz_FqxPy-m0aXU_zv0pw2S2brGSQi-AWLdgiSe9QMJ8nk0CwcIi6Ob2sjX-eI8EWSxRGfIZWPLhmRXNjuFtwXpO8-hBxEcUT4ZKeFA0j5tUsafxnJI2KDu2aSWc7816TqF8kqWCpS6WY_9-0afVrBHRfOPO57I3pWdJJlq63E9CKSYMj71WO_Kg0clK_vBNY-1zacb02qV8DPEc11K-EpwXqR15Y_Uhb1A_Iq6369c2s789Rv2ZJo1Q_YiadKvUDol6onxRzw9WP1i-StIaGeB3Xb5OGNMAzqKEhJTwt0BD6whpC26IhQF5tNeTIzCr5HA1pljRKDaFm0qnSECDqhYZIMTdcQ7z6RdKroSF-x-21SUMa4DmuoSElPC3QEO-FNcRri4YAebXVkIGZVfI5GtIsaZQa4plJp0pDgKgXGiLF3HAN8esXSb-GhvQ6bVKQBnB6sIJ0XIKCOEQEJWLK0jZpif_CWuK3RUuADNtqybGZ1fI5WtIsaZRa4ptJp0pLgKgXWiLF3HAtAQ6qzhlfJjFnu9Vg7zd3s4Cz8JptsoMnq3TCfk2TSf4zm8tR3i-3CEPGxaaVbi5O46KJi0CojoX-S3JdnFe7-qM_rhx9zMQ6SWdoHggWT-6-Dr_4fB1EojyxkHGWRsE8-iuQZ110-yIlExbd5NN-1FRoyte2fM5F64LxDMVu52-PhPQ0MyEKJoNvwoQ0ZULJIU8kJkc2MiENiiE1rhiqR39cOXprA7pTDF-eiZZiCCQ5OeQJUAwtYUJ3mXQfM_FKSLq7nT0lUN-kbeWeJaIePbFyvwAwsXK_oGZCvQMTiYmV92S-spT21KW0p-zcL_Pc7dxXF_FyJesat6U9eqI70eJcUiOpXl7fQ0C1uxMGRtROdwJgonu3oeXGbfBEd6LFaaJGUm15mFEM1aPX7k4YGFE73QmAiW53QksxPFZubElXvacmave72p9ocZYBTBSuhxmmDTR-3XsGE4Nqp0UBQbHSoyCSB16uqBSoqGq7uG_jhp0AXpiVaaZmYufSA7z1alfEjPsYKM91OxhGLn47tyOSE37wMAAmdj63oWaisEYMqYhAnuu2MfRURACKbh9DT6arj_dIH9h2Swd8ByMDYGLn4xsQlOrtiCHujnr8lhoZABQ776aks8NyRR0AFVVy2w9GBpHc9oORATDRvfRMzBM7H--AFo9R5ypPGL-VRgZt8t6cJbcyABPdRoaWiggwsfMZD2jxVLsjZlREaPxWGhlUfX5IgfNDKp0fHowMgImdRgYExc7tiBqKwh0xw92Bxq_7bkpPUKUTxHJF9YGKqn7rxEojg0puu1FGholM7Fx6aiZ2GhnQ4rFzOwJAMepcZd_4gSMEK2_a1Ux0Gxl68hw4P7TTyAAWj-7HPIyEUu2OGFIR1eeHFDg_pOq3dew0MoA33ezcOQBQ7DQygHfdrHzMA4Ji1Ev_-_ZT6pf1POBlPU-y2y00MsYP__s3AAD__3E8wN4= +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzsm99u2zYUxu_3FASvWkyuTEp2HAMFgv4Zlm6LhyQYMAy-UCwuFmxLrkjHyYI81l5gTzZIrurItHikpAs50XeRFdmHv3N4PuqjdI_55zke4ouPP398f4k-nF5cnp69v0SvZus369foh_PRL2h2gz6NTs_QbI1GZ2h282aG3qLsPBqdf_h4jt79nh9hB8dJyM6CBeN4-Acm2MEUO9jDDvaxg3t47OBlmkwY50ma_ct9fsFpeIuHXQdH8XIlso_HDp4kKcPDeywiMWd4iC-Dqzk7Z0HIUreLHRwyEUTz_GdmNyfLNFoE6R128MUyiPkQddzsh0crMUQnWRg__YZEtGBD1P3nb745niSxYLGIklg6lSZrjlIWhEP05eKrO8GKjwboHXbwIrhFC7ZI0jsUzOfJJBAsHKJufu4qEJMp4yhZiWUWQhZw_p3FBwSPHxy8OdpwKMZ5dYemAZ-WR3iS_f_YwVwE1wwPyYPzNHD9HXBrGZxLHqOjbUNHK9Ftv2cVJ2nIUhaWvmmcXQn9yx7-PwZ8-imJYpa6ZKdw5-xP8eqEvH6bRtfT_K8SeHbLJisZsopedo5_niPBFksURnyGVjy4Zk-GuwXnNam5DxEXUTwRLulJ2TBiXM2Kxn9G0ajo0K6ZdLYj7zXJ-kWSCpa6VMr596YNq18jofvSmY9lb07Pkk6ydL2dhFYMGoy8Vxn5USlyUr_1E1gzXdpxPVtUswG6oxqqWULXctUkL6yapC2qCdTcVjX7ZurCc1SzWdEoVZOYSadKNYGsF6op5dxw1aT1GyitoT1ex_Vt0Z4G6AY1tKeEruXaQ19Ye2hbtAeoua32HJnZXZ-jPc2KRqk91Ew6VdoDZL3QHinnhmuPV7-BejW0x--4PVu0pwG64xraU0LXcu3xXlh7vLZoD1BzW-0ZmNldn6M9zYpGqT2emXSqtAfIeqE9Us4N1x6_fgP1a2hPr2OL8jQA14OVp-MSFMQhIigRU5baokH-C2uQ3xYNAqpvq0HHZnbZ52hQs6JRapBvJp0qDQKyXmiQlHPDNQjYiDtnfJnEnO12g73f3M0SzsJrtqkOnqzSCfs1TSb5z2wOR_l1uZUZMi42Z-nm4DQuTnERCNW2139Jrovzblc_-uPK6GMm1kk6Q_NAsHhy9zX84vN1EInywELGWRoF8-ivQB51cdkXmZmw6CYf9qNThd58PZePuTi7YDxDsXvxt0dCepqZEAWTwTdhQpoyoeRQJxKTIxuZkAbNkBrXDNXRH1dGb21Cd5rhyzPR0gyBIieHOgGaoSVM6C6T7mMmXglJd_diTwnUN2lZuWeKqKMnVq4XACZWrhfUTKh3YCIxsfKezFe20p66lfaUF_fLPHcv7qubeLmTdY1b0h490Z1ocS2pkVRPr_9DQrW7EwZm1E53AmCie7Wh5cZt8ER3osVlokZSbXmY0QzV0Wt3JwzMqJ3uBMBEtzuhpRkeKxe2pKteUxO1-13tT7S4ygAmCtfDDNMGil_3msHEpNppUUBQrPQoiOSBlzsqBTqq2i7u27hgJ4AXZmWZqZnYOfUAb73aFTHjPgaqc90OhpGT387liOSEHzwMgImdz22omSisEUM6IlDnum0MPR0RgKLbx9BT6ertPdIHlt3SBt_ByACY2Pn4BgSlejliiLujjt9SIwOAYufdlLR3WO6oA6CjSm77wcggktt-MDIAJrqnnol1YufjHdDkMWpf5QnxW2lk0CbvzVlyKwMw0W1kaOmIABM7n_GAJk-1O2JGR4Tit9LIoOr9QwrsH1Jp__BgZABM7DQyICh2LkfUUBTuiBnuDhS_7rspPUmVdhDLHdUHOqr6rRMrjQwque1GGRkmMrFz6qmZ2GlkQJPHzuUIAMWofZV98QNbCFbetKuZ6DYy9NQ5sH9op5EBTB7dj3kYCaXaHTGkI6r3Dymwf0jVb-vYaWQAb7rZuXIAoNhpZADvuln5mAcExaiX_vetp9Qv63nAy3qeZLdbaGSMH777NwAA__-E3RxV # This query verifies stats collection for WITH ORDINALITY and the hashJoiner. query T @@ -220,7 +220,7 @@ regions: table: kv@primary spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzUUcFu00AQvfMVozmiRYkdm8OeXKCohlKjJAIh5MPGO0pXsXfd3XVJFOWz-AG-DNkmokmblIA49Djv7dt5b94a3U2JHCfnl-evp_Ac3o6zD7C4hc_p9AKy8Zv06uwynX6BswkIdoCYIUNtJF2JihzyrxhgzrC2piDnjG2hdfcglUvkQ4ZK141v4ZxhYSwhX6NXviTkOBWzksYkJNnBEBlK8kKV3beL26S2qhJ2hQwntdCOwwtk-P4TeFURh-GP766fC6M9aa-MvkdZ882BJSE5xD0yW3naQtEQXiHDmfDFNTkwja8bz6F10gm3QIz5hmE__UrivJgT8mDD_jxtZqXSolR-NQh2w9KSiuZ-gH8wFp5i7G4N4VOsYfSXNYz-dw3RQWO__TTaWEmW5I6ZvFU-9uSBdBfCXb8zSpMdRLvpstZqErAkZMmIJRFLYpa8RHYodiWWUFFl7ApEWZpCeJIc-q5azt2U4KmqQSq3gMaJOW3pRy8WHj5ZfEqXY3K10Y72T_fgz8P2XiTn1N_fmcYW9NGaolvTj1mn6wBJzvds0A-p7qnW4F1xcFQc7YiDfXF4VDw6vnl0wuZwXxwdFcd7m_PNs58BAAD__1tGDfU= +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzcUUFv00wQvX-_YjTHT4sSOzaHPblAUQ2lRkkEQsiHjXeUrmLvurvrkijKz-IP8MuQbSqatDENiAvHeW_fzpv3tuhuSuQ4O788fzmH_-H1NHsHq1v4mM4vIJu-Sq_OLtP5JzibgWBHiAUy1EbSlajIIf-MAeYMa2sKcs7YFtp2D1K5Rj5mqHTd-BbOGRbGEvIteuVLQo5zsShpSkKSHY2RoSQvVNl9u7pNaqsqYTfIcFYL7Tg8Q4ZvP4BXFXEYf_vq-rkw2pP2yugHlDVfHFgSkkPcI4uNpzsoGsMLZFiJNVRUGbsBUZamEJ4kh55bCF9ckwPT-LrxHFqX3ad3QIz5jmE__bjSebEk5MGOPT2JzEqlRan8ZhTsB0FrKpqHx_2BsfAUY_crCv-1iia_WdHkb1cUHTX200-jjZVkSe6ZyVvlr548ct2FcNdvjNJkR9H-dVlrNQlYErJkwpKIJTFLniM7dvZQVy3nbkrwVNUglVtB48SSnlxleDyy-JQup-Rqox0dRvfoz-M2L5JL6vN3prEFvbem6Nb0Y9bpOkCS8z0b9EOqe6o1eF8cDIqjPXFwKA4HxZPhzZMTNoeH4mhQHB9sznf_fQ8AAP__6tMgPQ== # Verify that EXPLAIN ANALYZE on an unsupported query doesn't return an error. statement ok @@ -273,7 +273,7 @@ regions: table: kv@primary spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzslMuO2j4Uxvf_p7DOapCMcuWvKivailajXqiYEV1ULEx8RC0SO2M7XIp4rL5An6yKQ6YTmCnpEomlz5eP4993zNmBecgggbvRx9Hbe8JWi5tlj4ynowm56ZF3k_EnslwBBak4fmY5Gki-QQAUQqAQAYUYKAxgRqHQKkVjlK4-2TnDLd9A4lMQsihtVZ5RSJVGSHZghc0QErhn8wwnyDhqzwcKHC0TmWuzXA0LLXKmt0DhrmDSJKTvVY3HpU3IsLrGhymxIseE-L9-mvqcKmlRWqHkiaTV2hCNjCfkYJ5vLTalV-QNUJgzm35HQ1Rpi6pNdSnnawoBzPYU6tMByli2QEiCPX0B_A9vKZXmqJG3WGf7Z6L5KiRXa9TeoJ3L6-n7m2HQe8yhSgQ3mJanzDnbkBxzpbeEZZlKmUWeEN-BVpp5yIjFvCBcmCUpDVtgI5_NYfBiDmErh6D7AwjOPwAv7HvRpTyBsDt62AE96nvxpaBH3dGjDuhx3_0LLgI97o4ed0Af9C8F_Myqn6AplDR4tPme_2W_2ojIF1ivT6NKneIXrVLXpj6Onc8VOBpbq0F9uJVOchd8ag7-av6_ZfaPzeG_dHYojgok2rXSS5IxizLdPg6oqa-ZsO3RcTSoBcvED3Y618Z2GG6KYoWHATdSM-VGqyfdqDmaatU__cDv_BDakUTXSI4jia-RHEcyuEayn-3_-x0AAP__U2vLVg== +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzslduO2jwQx--_p7DmapGMcuRTlSvailarHqjYFb2ouDDxiFokdtZ2OBTxWH2BPlkVh2w3sIf0sohLzz__zMxvJs4OzF0GCdyMPo7e3hK2Wlwte2Q8HU3IVY-8m4w_keUKKEjF8TPL0UDyDQKgEAKFCCjEQGEAMwqFVikao3T1yM4ZrvkGEp-CkEVpq_CMQqo0QrIDK2yGkMAtm2c4QcZRez5Q4GiZyFya5WpYaJEzvQUKNwWTJiF9r0o8Lm1ChlUZH6bEihwT4v_6aepzqqRFaYWSJ5JWa0M0Mp6Qg3m-tdiEXpE3QCFnG5JjrvSWsCxTKbPIE-I7bc5s-h0NUaUtqhKqgt07m0AAsz2F-nRo2Fi2QEiCPX0Cyh8WpVSao0be4jDbP4Ltq5BcrVF7gzaz19P3V8Ogd8-oooUbTMtTHs81WmnmLiMW84JwYZakNGyBnTkMnuQQtjgE3ZcjeHk5vLDvReewHmF3LGEHLFHfi88BS9QdS9QBS9x3X88_jyXujiXugGXQPwcoL_x2JmgKJQ0e3bSPv9mvbmDkC6yva6NKneIXrVKXpj6Onc8FOBpbq0F9uJZOcgU-NAfPmv9vmf1jc_g3mV0rriuQaNdKL0nGLMp0ez-8Jr5mwrbHytGgFiwTP9jpzBvbYfApihUeht9IzQY0Wr0FjZqjqX4tDx_wOy9CG0l0QXKMJL4gOUYyuCDZz_b__Q4AAP__hj_5Cg== # Very simple query to make it easier to spot regressions when rewriting results # in test files. @@ -300,7 +300,7 @@ regions: table: kv@primary spans: [/0 - /0] · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyMkFFLwzAUhd_9FZfzHGn7GhCGUnFsbtLN-SB9yNrLLO2SmqTTMfqz_AP-MmkjiojgS-B8J_dczj3BPTeQWKXz9GpNNV1ny1uqD_Rwk2Yp1XRBMQS0KXmh9uwgH5EgF2itKdg5Ywd0Gj9My1fIWKDSbecHnAsUxjLkCb7yDUNirbYNZ6xKttEQXLJXVTPG1odJa6u9skcIrFqlnaQojuLz4YkW9_M5BJadlzRJIDDbkK_2LCl-f3NBF0Z71r4y-pdlzYsjy6qUY5_ZhrZHz1-ILiGwVb54Ykem8-2wZvg4zn2DvBcI6rOf82rHkEkv_n-DjF1rtOMf9f9KjvtcgMsdhzs709mC76wpxjVBLse5EZTsfHCTIKY6WH3en30EAAD___6pnbQ= +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyMkdFKwzAUhu99isO5jrS9DQhDqTg2N-nmvJBeZO1hlrZJTU7nxuhj-QI-mTSRiYjgTeD__-RLzp8TutcGJa7SeXqzhhpus-U91Ht4ukuzFGq4ghgFalPSQrXkUD5jgrnAzpqCnDN2tE5-w7Q8oIwFVrrrebRzgYWxhPKEXHFDKHGttg1lpEqy0QguiVXVeGy9n3S2apU9osBVp7STEMVRfDku0eJxPkeBy54lTBIUONsAVy1JiD_eXdCF0UyaK6N_Rda8ObCkSunnmW1ge2Q6W3CNAlt1gJZaY4-gmsYUiumcbRUXL-TA9NyNTxghnvlt5IPAoL5md6x2hDIZxP_7ych1Rjv6Uc1f5HjIBVK5o_AHzvS2oAdrCn9NkEt_zhslOQ5pEsRUh2jIh4vPAAAA__-eiabY # Test a query that has a subquery and a postquery. statement ok @@ -389,6 +389,6 @@ regions: actual row count: 1 label: buffer 1 · -Diagram 1 (subquery): https://cockroachdb.github.io/distsqlplan/decode.html#eJysUtGK2zAQfO9XiH1KQEfsHIWip0tLCiGuUxJfoBRzKPLiE7UlV1o3l4Z8Vn-gX1Zsx-2Zo2lL71EzGmlmd47gPxcgYBFv5uuELeJkxdS9LjK2nUW38w0bhZyNNvNo_iZhpTajaszerlfvWCUdGhqPgYOxGcayRA_iI4TA4SWkHCpnFXpvXQMf20uL7AFEwEGbqqYGTjko6xDEEUhTgSAgtle2mkyBQ4YkddE-ig-oatLWMNIlChZ8_-aBw06SukfPbE1VTYIFwMHZ_S8ghPTEoTud__MkcwRxfeKPPIWXPSVyV-AaZYZuEgyddWO4qZwupTsAh00ljRfsCjhEutTEmoEst0Pjyy1T1hCap5mWW9ZGcCgz0Yt3B8IeesVe_1_08F-iz_LcYS7Jukk4TD6LP9zFq-Quvo2i0U3YFOH51zQdeP1DddboK2s8Dnz-7uXglHLALMeunt7WTuF7Z1X7TXdctboWyNBTx153h4XpqMbgY3F4UTy9LJ5eFAdDcRulTQUGaW_dJ1ZIQqMOPyff43upabiTDD06LQv9VT5dWC87F1Gh_oLnMvZU38ie61rZsyV6L_PBheBvi5CeXvwIAAD__2aUhTI= +Diagram 1 (subquery): https://cockroachdb.github.io/distsqlplan/decode.html#eJysUuGK2zwQ_P89xbK_EtARO8cHRb8uLSmEpE5JcoFSwqHIi0_Ullxp0yQNeay-QJ-s2I7bM0fTlvanZjTS7OycMHzMUeIkWY4XK5gkqznoR5OnsB7N7sdL6MUCesvxbPxqBYWxvbIPrxfzN1AqT5b7fRRoXUqJKiigfI8xCvwfNwJL7zSF4HwFn-pLk_SAMhJobLnjCt4I1M4TyhOy4ZxQYuJuXDkYosCUWJm8fpQOpHdsnAU2BUmIvn4JKHCrWD9SALfjcscSIhTo3f4HEOPmLLA5Xf4LrDJCeXsWTzzF1z2t1DanBamU_CDqOmtiuCu9KZQ_osBlqWyQcIMCZ6YwDFUg03XX-HQN2lkm-3ym6RrqETypVLbi7ZGphV7ASxRYqAMUVDh_BJXnTiumVEJUc38RS_wnsYyyzFOm2PlB3E1llLx7SOarh-R-NuvdxVVJ_v0Khx2vv6jVgkLpbKCOz5-9HJ03AinNqKlucDuv6a13uv6mOc5rXQ2kFLhhb5vDxDZUZfCpOL4qHl4XD6-Ko664HqWeCi3x3vkPkCsmq4_fk2_xvTLc3UlKgbxRufmsni-slV1Kqsl8oktRW6pta8s1jW3ZgkJQWedC9LtF2Jz_-xYAAP__g4SOVg== Diagram 2 (main-query): https://cockroachdb.github.io/distsqlplan/decode.html#eJyMj89K80AUxfffU1zOqoWBL9nOTiRCoLbSVjeSRZxc2oF0bpy5wULJY_kCPpk0I4gLweX53Tl_5oL02sOiXu-q7Z7q9X5D7uj7jp5uVo_VjhalocWuWlW3ezr5sBiWdLfd3NPQRg66XMIgSMfr9sQJ9hklGoMhiuOUJF7RZX5Qd2fYwsCHYdQrbgycRIa9QL32DIteXNuTkzEoFf8LGHSsre_nYD6zG9VLIPUntlR8vCcYvLTqjpxIRh1GtXR1RXn7BiWaySCrr96k7YFhy8n8fduW0yAh8Y9RvyUXU2PA3YHz_5OM0fFDFDfXZLmZfTPoOGm-llnUIZ-mZvr3GQAA__9Sm4hi Diagram 3 (postquery): https://cockroachdb.github.io/distsqlplan/decode.html#eJy0k9Fu2jAUhu_3FEfnCiRLJNCLyVd0E0gpWTJBys3EhXEOrbdgZ7ajFSEeay-wJ5sSt9pY1Who6x3_b__Hn3-TI7qvFXJMstVsWUCSFTnIe1WVsL5Ob2crGMQMBqtZOntfwF7pQT2E-TL_ALWwpP1wiAy1KSkTe3LIP2GMG4a1NZKcM7a1jt2GpHxAHjFUum58a28YSmMJ-RG98hUhx8pIUYGTQsO22e3IQjSKkGFJXqiqG583nsN0jAzpgWTjldHg1Z44RD--O2S4FV7ekwPT-Lrd2-at-fbLiHFzYhjUI4fz4o6Qxyf296xzVXmyZEfxOWDwOUxjSFaQ5QVkt2n6KrzjS3hvjNJLEiXZ0ficuDjUxCGdzQu4zooEbvIkQ4bhgae1VXthD8gwNeZLU8NnozQY3d4Q2eN7tL-6w6FFb5mftPOiqs5vvFg_09JoT_p5OYt1NxAsiTJMXaxhe_D0ZL2Fd_9QbfRitZNLqg1_W7LWWFC7QByPJuct_3_Gq0sYl-Rqox2dQb00OTptGFJ5R-Hzdaaxkj5aI7tjgsy7XGeU5HxYjYNIdFhqAX8Px73hcX943Bue9IcnveGrP8Kb05ufAQAA__9GX6z9 diff --git a/pkg/sql/logictest/testdata/logic_test/inverted_index_geospatial b/pkg/sql/logictest/testdata/logic_test/inverted_index_geospatial index 47fb1476b34a..66d5bb175b4a 100644 --- a/pkg/sql/logictest/testdata/logic_test/inverted_index_geospatial +++ b/pkg/sql/logictest/testdata/logic_test/inverted_index_geospatial @@ -78,7 +78,7 @@ regions: table: geo_table@geom_index spans: 31 spans · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzMleFO40YQx7_3KUbzBVBdZdc2adiqUgqYNm0hyIlaoTpCiz0NFrbX7G5aI5THuhe4JzvZJhwhirnc3YfLh41mxv_1zG9m149o7jMUOAn-DE6mcAdn4fgc5qSurbzJCP7-LQgDMPY6LSxpQ7E1-3uTcHT6s9s_4oOfLseji-m-zxhjHjR_zDvYE-LXYHweTMMrp94rP4BxeBqEcHwFd-hgoRK6kDkZFP8gx5mDpVYxGaN07XpsHhglFQrmYFqUC1u7Zw7GShOKR7SpzQgFTuscQ5IJ6R5DBxOyMs2abZ9LGNYJXKdFQhU6OCllYQT0IjyOourfJIoqzqKoYm8t-MOuGh4hyCIBj4Gyt6QNOvjHX2DTnASw9--e7FgVlgqbqmIjpNX_BjTJRIDfem4eLK1cngvH6OCNtPEtGVALWy6sgJpDI1w5fJwtHWytJ47Gyjmh4Evn01mPiv9IW0rO0sySJt3j68BX8aAqNagChlyAqWmDsVJb0dDzfjyMIuayKGLsrQWBimRXWQ19g_q4xjCs820KbLi2SFvbWJll6_Sponix2ZRcVpBTrvQDyCxTsbSUCGBNI-qYuc_AUl5Ckpo7WBg5p1X4zT65W_vk7tKn31VaPB0Jd9uRKHWaS_3wEY0zdF_RcbvofPYYu5tjzPsNni3Av4Catwu156n21pm1fvH6BmSc8fquc5nb7x-xl7-T_i984PPWGLABH_h-4PM98fJSHLoHW-eyk_zXx-TvgmmitCXd89chDfn339qROdylqpBMqQpDa1Vt25ktZw5SMqf2U2XUQsd0qVXcvKY1x42ucSRkbBvlrTEq2lCd4Esx7xS73WK3U-x1i71Osd8t9jvFh6_Es-V3HwIAAP___4y3QA== +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzMleFO40YQx7_3KUbzBVBdZdc2adiqUgqYNm0hyIlaoTpCiz0NFrbX7G7ujFAe617gnuxkGzhCFEPu7sPlg6OZyX-z8_vPru_R3GYocBL8HRxN4QZOwvEpzEldWnmVEfz7RxAGYOxlWljShmJrdncm4ej4V7d_wAe_nI9HZ9NdnzHGPGi-mLe3I8Tvwfg0mIYXTr1Wvgfj8DgI4fACbtDBQiV0JnMyKP5DjjMHS61iMkbpOnXf_GCUVCiYg2lRLmydnjkYK00o7tGmNiMUOK33GJJMSPcYOpiQlWnWLPvUwrDewGVaJFShg5NSFkZAL8LDKKr-T6Ko4iyKKvbaA3_aVsMjBFkk4DFQ9pq0QQf_-gdsmpMA9vHDQxyrwlJhU1WslbR6b0CTTAT4bebqztJjynPhEB3MZQU55UrfgcwyFUtLiQDW1K6kja_JgFrYcmEF1IyaRR8TPs6WDrbRA2Nj5ZxQ8KXzdh9GxTvSlpKTNLOkSff4qhmP9aAqNagChlyAqZ0AY6W2oiHr_bwfRcxlUcTYaw8EKpJtZbUha46MawzDer9Ngw3zFncbGyuzbNUZqiherBvWZURdM7cZWMpLSFJzAwsj5_Rmn9yNPrnb-PSnSouH4-JuOi6lTnOp7z6jcYbuCzpuF50vHnF3fcR5v8GzAfhXUPO2ofY01d4qszYvXt6OjDNe34Muc_v9A_b8c9T_jQ983gYDNuAD3w98viOeX5hDd2_jXHaS__aY_G0wTZS2pHv-KqQh__F7OzL723QVkilVYWilq00rs-XMQUrm1L7GjFromM61ipu_acNxo2sSCRnbVnkbjIq2VG_wuZh3it1usdsp9rrFXqfY7xb7neL9F-LZ8odPAQAA__8NeMBk statement ok DROP TABLE geo_table @@ -164,7 +164,7 @@ regions: table: geo_table@geom_index spans: 31 spans · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzMleFO40YQx7_3KUbzBVBdZdc2adiqUgqYNm0hyIlaoTpCiz0NFrbX7G7aIJTHuhe4JzutTTgCwncRd9Llw0bzH__XO7_ZXd-juS1Q4CT6Mzqawg2cxONTmJO6tPKqIPj7tyiOwNjLvLKkDaXW7O5M4tHxz37_gA9-Oh-Pzqa7IWOMBdD8sWBvR4hfo_FpNI0vPDdXuQfj-DiK4fACbtDDSmV0JksyKP5BjjMPa61SMkZpJ903D4yyJQrmYV7VC-vkmYep0oTiHm1uC0KBU7fGmGRGusfQw4yszItm2scShm4Bl3mV0RI9nNSyMgJ6CR4myfLfLEmWLHAD-8SAP2zr4QmCrDIIGCh7Tdqgh3_8BTYvSQB7_-4hTlVlqbK5ql6ktPrfgCaZCfBb5erO0lrifThED6-kTa_JgFrYemEFOA6NcS34OFt52EYPHI2Vc0LBV97nsx5V_5G2lJ3khSVNusc3ga_z0bLWoCoYcgHG0QZjpbaioRf8uJ8kzNFjDlLngEBVtq3NQX9BfewwDN16mwIbri3SNjZWFsUmfVpSunjZlFIuoaRS6TuQRaFSaSkTwJpGuJy5LcBSWUOWmxtYGDmndfoNffK36dPvKq8ejoT_2pGodV5KffcRjTf0t6HzFbbxK8DfQC3Yhtrjrg42mbW6eH4DMs64u-t85vf7B-zp76j_Cx-EvA0GbMAHYRiFfEc8vRSH_t4X3ZdvwBRug2mitCXdCzchDfn339qR2d-mqphMrSpDG1W9NjNbzTykbE7tp8qohU7pXKu0eU0bjhtfI2RkbJvlbTCq2pRb4FMz7zT73Wa_0xx0m4NOc9htDjvN-8_Ms9V3HwIAAP__EHC3Qg== +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzMleFO40YQx7_3KUbzBVBdZdc2adiqUgqYNm0hyIlaoTpCiz0NFrbX7G7uglAe617gnuy0NnAEhO8iOOnyYaOZ8X-98_vvrm_RXBcocBL9HR1M4QqO4vExzEmdW3lREPz7RxRHYOx5XlnShlJrtrcm8ejwV7-_xwe_nI5HJ9PtkDHGAmj-WLCzJcTv0fg4msZnnpur3IFxfBjFsH8GV-hhpTI6kSUZFP8hx5mHtVYpGaO0S902D4yyJQrmYV7VC-vSMw9TpQnFLdrcFoQCp26NMcmMdI-hhxlZmRfNtA8tDN0CzvMqoyV6OKllZQT0EtxPkuX_WZIsWeAG9oUBf9pUwxMEWWUQMFD2krRBD__6B2xekgD28cNdnKrKUmVzVT0rafXegCaZCfDbzMWNpfsU78M-eljKJZRUKn0DsihUKi1lAlhTu5A2vSQDamHrhRXgGDWT3id8nK08bKM7xsbKOaHgK-_rfRhV70hbyo7ywpIm3ePrZtzXo2WtQVUw5AKMcwKMldqKhmzw826SMEeWOYCdAwJV2aYyZ8gzR8YOw9Ctt2mwYd7ibmNjZVGsO0NLShfPDesywtXMdQGWyhqy3FzBwsg5vYFP_iY-_any6u64-C8dl1rnpdQ3n9F4Q38TOt9gi78A_BXUgk2oPezqYJ1ZmxdPb0fGGXf3oM_8fn-PPf4d9H_jg5C3wYAN-CAMo5BviccX5tDfedN9-QpM4SaYJkpb0r1wHdKQ__i9HZndTbqKydSqMrTW1Uszs9XMQ8rm1H7GjFrolE61SpvXtOG40TWJjIxtq7wNRlVbcgt8LOadYr9b7HeKg25x0CkOu8Vhp3j3iXi2-uFTAAAA__8evcBm # Also works when creating an index. statement ok @@ -226,4 +226,4 @@ regions: table: geo_table@geom_index spans: 31 spans · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzMleFO40YQx7_3KUbzBVBdZdc2adiqUgqYNm0hyIlaoTpCiz0NFrbX7G7aIJTHuhe4JzutTTgCwncRd9Llw0bzH__XO7_ZXd-juS1Q4CT6Mzqawg2cxONTmJO6tPKqIPj7tyiOwNjLvLKkDaXW7O5M4tHxz37_gA9-Oh-Pzqa7IWOMBdD8sWBvR4hfo_FpNI0vPDdXuQfj-DiK4fACbtDDSmV0JksyKP5BjjMPa61SMkZpJ903D4yyJQrmYV7VC-vkmYep0oTiHm1uC0KBU7fGmGRGusfQw4yszItm2scShm4Bl3mV0RI9nNSyMgJ6CR4myfLfLEmWLHAD-8SAP2zr4QmCrDIIGCh7Tdqgh3_8BTYvSQB7_-4hTlVlqbK5ql6ktPrfgCaZCfBb5erO0lrifThED6-kTa_JgFrYemEFOA6NcS34OFt52EYPHI2Vc0LBV97nsx5V_5G2lJ3khSVNusc3ga_z0bLWoCoYcgHG0QZjpbaioRf8uJ8kzNFjDlLngEBVtq3NQX9BfewwDN16mwIbri3SNjZWFsUmfVpSunjZlFIuoaRS6TuQRaFSaSkTwJpGuJy5LcBSWUOWmxtYGDmndfoNffK36dPvKq8ejoT_2pGodV5KffcRjTf0t6HzFbbxK8DfQC3Yhtrjrg42mbW6eH4DMs64u-t85vf7B-zp76j_Cx-EvA0GbMAHYRiFfEc8vRSH_t4X3ZdvwBRug2mitCXdCzchDfn339qR2d-mqphMrSpDG1W9NjNbzTykbE7tp8qohU7pXKu0eU0bjhtfI2RkbJvlbTCq2pRb4FMz7zT73Wa_0xx0m4NOc9htDjvN-8_Ms9V3HwIAAP__EHC3Qg== +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzMleFO40YQx7_3KUbzBVBdZdc2adiqUgqYNm0hyIlaoTpCiz0NFrbX7G7uglAe617gnuy0NnAEhO8iOOnyYaOZ8X-98_vvrm_RXBcocBL9HR1M4QqO4vExzEmdW3lREPz7RxRHYOx5XlnShlJrtrcm8ejwV7-_xwe_nI5HJ9PtkDHGAmj-WLCzJcTv0fg4msZnnpur3IFxfBjFsH8GV-hhpTI6kSUZFP8hx5mHtVYpGaO0S902D4yyJQrmYV7VC-vSMw9TpQnFLdrcFoQCp26NMcmMdI-hhxlZmRfNtA8tDN0CzvMqoyV6OKllZQT0EtxPkuX_WZIsWeAG9oUBf9pUwxMEWWUQMFD2krRBD__6B2xekgD28cNdnKrKUmVzVT0rafXegCaZCfDbzMWNpfsU78M-eljKJZRUKn0DsihUKi1lAlhTu5A2vSQDamHrhRXgGDWT3id8nK08bKM7xsbKOaHgK-_rfRhV70hbyo7ywpIm3ePrZtzXo2WtQVUw5AKMcwKMldqKhmzw826SMEeWOYCdAwJV2aYyZ8gzR8YOw9Ctt2mwYd7ibmNjZVGsO0NLShfPDesywtXMdQGWyhqy3FzBwsg5vYFP_iY-_any6u64-C8dl1rnpdQ3n9F4Q38TOt9gi78A_BXUgk2oPezqYJ1ZmxdPb0fGGXf3oM_8fn-PPf4d9H_jg5C3wYAN-CAMo5BviccX5tDfedN9-QpM4SaYJkpb0r1wHdKQ__i9HZndTbqKydSqMrTW1Uszs9XMQ8rm1H7GjFrolE61SpvXtOG40TWJjIxtq7wNRlVbcgt8LOadYr9b7HeKg25x0CkOu8Vhp3j3iXi2-uFTAAAA__8evcBm diff --git a/pkg/sql/logictest/testdata/logic_test/vectorize_local b/pkg/sql/logictest/testdata/logic_test/vectorize_local index 081962a52c76..8064973cdfbd 100644 --- a/pkg/sql/logictest/testdata/logic_test/vectorize_local +++ b/pkg/sql/logictest/testdata/logic_test/vectorize_local @@ -59,7 +59,7 @@ regions: table: a@primary spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyMkMFO8zAQhO__U1hz9i8SDhx8qkBFqgoUtRUXlIMbr4ql1A7ejaCK8li8AE-GErcHhJA4zjfeWe_04NcGBpv53fxmq6y6Xa_ulYVGiI4e7IEY5hklKo02xZqYYxpRPz1YuHeYQsOHtpMRVxp1TATTQ7w0BIOt3TW0JusoXRTQcCTWN1OsnbXJH2w6QmPT2sBG_YfGqhOjZiU0lk9K_IGMKj4_OOs6BqEgPoYfVopvrBJZZ9SlLopTwO4odMbllVr6a2jsrNQvxCp20o7bxo9N42eQA6pBI5PTcSx2TzDloP9ewJq4jYHp2-2_JRdDpUFuT7lkjl2q6THFelqT5Wqam4AjluyWWSxCtoZq-PcVAAD__yPumVo= +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJyMkcFq6zAQRffvK4a71uPZb9GFVqElhZC2KUnopngxsYZUYEuuJNOE4M_qD_TLiq1kUUqhy3uufTQanRBfG2hs5nfzmy0x3a5X98RQcN7IA7cSoZ9RolLogq8lRh9GdJo-WJgDdKFgXdenEVcKtQ8CfUKyqRFobHnXyFrYSPhXQMFIYttMWp51wbYcjlDYdOyipr9QWPVJ06yEwvKJkm1FU_HxHnOuvUvikvXuWxX8W6QgbDT9V0VxFuyOSS64vKKlvYZCywdqpfXhSNw0vuYkRlNBY7fjVL9IJN-nbpxkHHpSX0CWV4NCJueLx8R7gS4H9fvlrCV23kX5spefzMVQKYjZS36A6PtQy2Pw9XRMjqvpvwkYiSm3ZQ4Ll6uhGv58BgAA__9Zk6J- query T EXPLAIN ANALYZE (DISTSQL) SELECT c.a FROM c JOIN d ON d.b = c.b @@ -96,7 +96,7 @@ regions: table: c@sec spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJykkl-L00AUxd_9FJfzPNamDyIDQlFW6Lo20l18kTxMZi5rNJ0bZya4S-nH8gv4ySQzWbAWxT-P59ycufd3yAHxcw-N64uri5c3ZBeGXu3qN2Tpst5syVG9Jbdo6TnZRQsFL463Zs8R-j0qNApDEMsxSpisQ_5g4-6glwqdH8Y02Y2ClcDQB6Qu9QyNG9P2vGPjODxZQsFxMl2fn7XryBYK14PxUdNjKNRj0rSu1HoFhdfvKHV71rT89jUWbcUn9qkTfzYK8iVSYOM0zeH2PvGDVT2lF1BoTbIfOJKMaZhWTRfl4IOxQnNUKGomisncMnR1VH9OfSmdn6GrU2i3HkK3N-EeClcin8aBPkrnSbymTD1XgHlB5ipIRcdk-v6M_t-Kqs6LepZ74ju243n6P-pb_U19O46D-Mgn1f3q5eWxUWB3y-XHjDIGy2-D2LymyDrnsuE4pjKtitj4MpoO_DFc_Ta8-incHB99DwAA__8TeBlu +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJykkt-K1DAUxu99isO5jmM7FyIBYVBWmHWdyuzijfQiTQ5rNM2pSYozDPNYvoBPJk264FgU_1x-39fv5JwfPWH87FDi7dXN1cs70CsFr_bNG9Bw3Wx3YKDZgVl18Bz0qkOBng3tVE8R5XussRU4BNYUI4fJOuUPtuaAshJo_TCmyW4Fag6E8oTJJkco8U51jvakDIUnFQo0lJR1eazeRNIo8HZQPkp4jAKbMUnY1GKzRoGv30GyPUmovn2NRWv2iXyy7BdR4C8RAikjYS53x0QPVv0UXqDAXh2gp57DEZRzrFUiI6HKWaeS_kAReEzDtMa0bR76YKyxPQssar42JnVPKOuz-HMi12z9DKS-BGI2Q7C9CkcUeMP8aRzgI1sP7CVkIjMenB_IN5dzi45JObcg828Q6yXEZ5kTHUiPy_Z_4Fv_Db49xYF9pAt0v5pcnVuBZO6p_LSRx6DpbWCdnymyyb1sGIqppHURW1-iacEfy_Vvy-ufyu350fcAAAD__wxXIpI= query T EXPLAIN (OPT, VERBOSE) SELECT c.a FROM c INNER MERGE JOIN d ON c.a = d.b @@ -188,7 +188,7 @@ regions: table: d@primary spans: FULL SCAN · -Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzMk8GO0zAQhu88xWhOoDW7dbriYGmlChRQF5qgdMUF5eDaQzYisbO2I1pVfSxegCdDSajYdMtCxWVvmX_mt-ebcbbo7yoUuIw_xG9uQJ1LeJulC1AwT5I4g0WcvYvhOp0noCFN-oIr0OcrZGispkTW5FF8Ro45w8ZZRd5b10nbvmCu1ygmDEvTtKGTc4bKOkKxxVCGilDgjVxVlJHU5C4myFBTkGXVH6tmnhQyXDbSeAEvkWHaBgEzjgzff4JQ1iRg8uO7H2JlTSATSmsepJz95sGR1AKiQVltAu0l_gpeI8OVDOqWPNg2NN09XTu9cS9EmO8YDtEvHB9kQSj4jv078tK6QO6Cj2ln_AwZ0ppU-xChlmuoqbZuA7KqrJKBtIBJ33aX83cVBKob0KX_Cq2XBe3T_0EVnUJ1f5HRGE3PGlfW0m2OLTN6csuc_hH7N21rrNPkSI9I8875t5Ijs1uQK-jalobcxXQ8u4q-hOczfvbiypXF7fA5-hGe1Iu5POXFZOQbazwdjvDoyZNubqQLGvbgbesUfXRW9dcMYdr7ekGTD0OWD8HcDKmuwftm_qh5OjLzQ3N0gjk6NE8fNV8etJ3vnv0MAAD__xmY2Xc= +Diagram: https://cockroachdb.github.io/distsqlplan/decode.html#eJzUU8Fu00AQvfMVozmBurRZp-KwUqUIZFAKsZFTcUE-bHYH18LedXfXIlGUz-IH-DJkm4o6DYFIHOCWeTNv8t6b9Rb9XYUCl_G7-NUNqHMJr7N0AQrmSRJnsIizNzFcp_MENKRJP3AF-nyFDI3VlMiaPIqPyDFn2DiryHvrOmjbD8z1GsWEYWmaNnRwzlBZRyi2GMpQEQq8kauKMpKa3MUEGWoKsqz6tWrmSSHDZSONF_AcGaZtEDDjyPDtBwhlTQIm3776oVbWBDKhtOZRy9kvHhxJLSAakNUm0D3EX8BLZFjLNdRUW7cBWVVWyUBawKTvrWRQt-TBtqHpNHRS-6X3QIT5juFQ_bDqgywIBd-xP49jaV0gd8HHScz4GTKkNan2sb1jsruev6sgUN2ALv1naL0s6C-4ik5x9fDI0dianjWurKXbHDp09F8devrLSH4m0RrrNDnSoxTyjvm7kQO5LsgVdG1LQ-5iOs61ok_h6YyfPbtyZXE7_Bx9QP_Ua7o85TVl5BtrPO1HeHDzpMuNdEHDHbxtnaL3zqr-b4Yy7Xk9oMmHocuHYm6GVifwIZkfJU9HZL5Pjk4gR_vk6VHy5Z7sfPfkewAAAP__1qTrvw== statement ok RESET vectorize; RESET distsql