Skip to content

Commit 40c4c0d

Browse files
craig[bot]DrewKimball
andcommitted
Merge #148105
148105: opt: avoid delete cascade fast path for regional by row tables r=mgartner a=DrewKimball #### opt,testcat: allow defining the region column explicitly in opt tests This commit adds support for explicitly defining the `crdb_region` column for REGIONAL BY ROW tables in optimizer tests. This will allow testing scenarios like a computed region column. Epic: None Release note: None #### opt: avoid delete cascade fast path for regional by row tables We have a fast path for cascading deletes where the filters from the parent table are applied directly to the child table instead of joining from a buffer to the child table. This can result in an efficient `DeleteRange` operation in some cases, but in others, can result in a "less constrained" scan on the child table. In particular, it can result in visiting more regions than necessary for a regional-by-row child table. This commit prevents the fast path from applying for regional-by-row child tables unless the region column is restricted to a single value. It is possible to revert to the old behavior by disabling a new session var: `optimizer_disable_cross_region_cascade_fast_path_for_rbr_tables`. Informs: #146705 Release note (performance improvement): The optimizer will no longer apply a fast-path to deletes cascading to regional-by-row tables. This prevents the cascading delete from accessing more regions than necessary. Co-authored-by: Drew Kimball <[email protected]>
2 parents e4d1523 + 36c419a commit 40c4c0d

File tree

12 files changed

+1177
-858
lines changed

12 files changed

+1177
-858
lines changed

pkg/ccl/logictestccl/testdata/logic_test/regional_by_row_query_behavior

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3179,11 +3179,17 @@ vectorized: true
31793179
│ └── • delete
31803180
│ │ from: user_settings_cascades
31813181
│ │
3182-
│ └── • scan
3183-
│ missing stats
3184-
│ table: user_settings_cascades@user_settings_cascades_user_id_idx
3185-
│ spans: [/'ap-southeast-2'/'5ebfedee-0dcf-41e6-a315-5fa0b51b9882' - /'ap-southeast-2'/'5ebfedee-0dcf-41e6-a315-5fa0b51b9882'] [/'ca-central-1'/'5ebfedee-0dcf-41e6-a315-5fa0b51b9882' - /'ca-central-1'/'5ebfedee-0dcf-41e6-a315-5fa0b51b9882'] [/'us-east-1'/'5ebfedee-0dcf-41e6-a315-5fa0b51b9882' - /'us-east-1'/'5ebfedee-0dcf-41e6-a315-5fa0b51b9882']
3186-
│ locking strength: for update
3182+
│ └── • lookup join
3183+
│ │ table: user_settings_cascades@user_settings_cascades_user_id_idx
3184+
│ │ equality: (crdb_region, id) = (crdb_region, user_id)
3185+
│ │
3186+
│ └── • distinct
3187+
│ │ estimated row count: 100
3188+
│ │ distinct on: id, crdb_region
3189+
│ │
3190+
│ └── • scan buffer
3191+
│ estimated row count: 100
3192+
│ label: buffer 1000000
31873193
31883194
└── • constraint-check
31893195

pkg/sql/exec_util.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4194,6 +4194,10 @@ func (m *sessionDataMutator) SetUseImprovedRoutineDependencyTracking(val bool) {
41944194
m.data.UseImprovedRoutineDependencyTracking = val
41954195
}
41964196

4197+
func (m *sessionDataMutator) SetOptimizerDisableCrossRegionCascadeFastPathForRBRTables(val bool) {
4198+
m.data.OptimizerDisableCrossRegionCascadeFastPathForRBRTables = val
4199+
}
4200+
41974201
// Utility functions related to scrubbing sensitive information on SQL Stats.
41984202

41994203
// quantizeCounts ensures that the Count field in the

pkg/sql/logictest/testdata/logic_test/information_schema

Lines changed: 207 additions & 206 deletions
Large diffs are not rendered by default.

pkg/sql/logictest/testdata/logic_test/pg_catalog

Lines changed: 427 additions & 424 deletions
Large diffs are not rendered by default.

pkg/sql/logictest/testdata/logic_test/show_source

Lines changed: 213 additions & 212 deletions
Large diffs are not rendered by default.

pkg/sql/opt/memo/memo.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ type Memo struct {
207207
internal bool
208208
usePre_25_2VariadicBuiltins bool
209209
useExistsFilterHoistRule bool
210+
disableSlowCascadeFastPathForRBRTables bool
210211

211212
// txnIsoLevel is the isolation level under which the plan was created. This
212213
// affects the planning of some locking operations, so it must be included in
@@ -311,6 +312,7 @@ func (m *Memo) Init(ctx context.Context, evalCtx *eval.Context) {
311312
internal: evalCtx.SessionData().Internal,
312313
usePre_25_2VariadicBuiltins: evalCtx.SessionData().UsePre_25_2VariadicBuiltins,
313314
useExistsFilterHoistRule: evalCtx.SessionData().OptimizerUseExistsFilterHoistRule,
315+
disableSlowCascadeFastPathForRBRTables: evalCtx.SessionData().OptimizerDisableCrossRegionCascadeFastPathForRBRTables,
314316
txnIsoLevel: evalCtx.TxnIsoLevel,
315317
}
316318
m.metadata.Init()
@@ -488,6 +490,7 @@ func (m *Memo) IsStale(
488490
m.internal != evalCtx.SessionData().Internal ||
489491
m.usePre_25_2VariadicBuiltins != evalCtx.SessionData().UsePre_25_2VariadicBuiltins ||
490492
m.useExistsFilterHoistRule != evalCtx.SessionData().OptimizerUseExistsFilterHoistRule ||
493+
m.disableSlowCascadeFastPathForRBRTables != evalCtx.SessionData().OptimizerDisableCrossRegionCascadeFastPathForRBRTables ||
491494
m.txnIsoLevel != evalCtx.TxnIsoLevel {
492495
return true, nil
493496
}

pkg/sql/opt/memo/memo_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,11 @@ func TestMemoIsStale(t *testing.T) {
579579
evalCtx.SessionData().OptimizerUseExistsFilterHoistRule = false
580580
notStale()
581581

582+
evalCtx.SessionData().OptimizerDisableCrossRegionCascadeFastPathForRBRTables = true
583+
stale()
584+
evalCtx.SessionData().OptimizerDisableCrossRegionCascadeFastPathForRBRTables = false
585+
notStale()
586+
582587
// User no longer has access to view.
583588
catalog.View(tree.NewTableNameWithSchema("t", catconstants.PublicSchemaName, "abcview")).Revoked = true
584589
_, err = o.Memo().IsStale(ctx, &evalCtx, catalog)

pkg/sql/opt/optbuilder/fk_cascade.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,39 @@ func (mb *mutationBuilder) tryNewOnDeleteFastCascadeBuilder(
225225
return nil, false
226226
}
227227

228+
// For a REGIONAL BY ROW child table, if the region column is part of the FK,
229+
// check that it is constrained to a single value. If this is not the case,
230+
// the fast path can be suboptimal, since joining against the parent buffer
231+
// will constrain the region column to a single constant value.
232+
if childTab.IsRegionalByRow() &&
233+
mb.b.evalCtx.SessionData().OptimizerDisableCrossRegionCascadeFastPathForRBRTables {
234+
// The regional column is the first in every index, including the primary.
235+
regionalColOrd := childTab.Index(cat.PrimaryIndex).Column(0).Ordinal()
236+
var regionalColID opt.ColumnID
237+
for i, colID := range fkCols {
238+
if fk.OriginColumnOrdinal(childTab, i) == regionalColOrd {
239+
regionalColID = colID
240+
break
241+
}
242+
}
243+
if regionalColID != 0 {
244+
regionalColIsConstrained := false
245+
for i := range filters {
246+
if eq, isEq := filters[i].Condition.(*memo.EqExpr); isEq {
247+
if v, leftIsVar := eq.Left.(*memo.VariableExpr); leftIsVar && v.Col == regionalColID {
248+
if opt.IsConstValueOp(eq.Right) {
249+
regionalColIsConstrained = true
250+
break
251+
}
252+
}
253+
}
254+
}
255+
if !regionalColIsConstrained {
256+
return nil, false
257+
}
258+
}
259+
}
260+
228261
var visited intsets.Fast
229262
parentTabID := parentTab.ID()
230263
childTabID := childTab.ID()

pkg/sql/opt/testutils/testcat/create_table.go

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,27 @@ func (tc *Catalog) CreateTable(stmt *tree.CreateTable) *Table {
115115
// so use type STRING instead.
116116
oid := types.String.Oid()
117117

118-
evalCtx := eval.MakeTestingEvalContext(cluster.MakeTestingClusterSettings())
119-
crdbRegionDef :=
120-
multiregion.RegionalByRowDefaultColDef(
121-
oid,
122-
multiregion.RegionalByRowGatewayRegionDefaultExpr(oid),
123-
multiregion.MaybeRegionalByRowOnUpdateExpr(&evalCtx, oid),
124-
)
125-
crdbRegionDef.Type = types.String
126-
stmt.Defs = append(stmt.Defs, crdbRegionDef)
118+
// Add a region column only if one doesn't already exist.
119+
hasRegionCol := false
120+
for _, def := range stmt.Defs {
121+
if colDef, ok := def.(*tree.ColumnTableDef); ok {
122+
if colDef.Name == tree.RegionalByRowRegionDefaultColName {
123+
hasRegionCol = true
124+
break
125+
}
126+
}
127+
}
128+
if !hasRegionCol {
129+
evalCtx := eval.MakeTestingEvalContext(cluster.MakeTestingClusterSettings())
130+
crdbRegionDef :=
131+
multiregion.RegionalByRowDefaultColDef(
132+
oid,
133+
multiregion.RegionalByRowGatewayRegionDefaultExpr(oid),
134+
multiregion.MaybeRegionalByRowOnUpdateExpr(&evalCtx, oid),
135+
)
136+
crdbRegionDef.Type = types.String
137+
stmt.Defs = append(stmt.Defs, crdbRegionDef)
138+
}
127139
tab.implicitRBRIndexElem =
128140
&tree.IndexElem{
129141
Column: tree.RegionalByRowRegionDefaultColName,

0 commit comments

Comments
 (0)