Skip to content

Commit

Permalink
sql,opt: add setting avoid_full_table_scans_in_mutations
Browse files Browse the repository at this point in the history
Fixes #79683

Release note (sql change): Added a new session setting
avoid_full_table_scans_in_mutations, which when set to true, causes
the optimizer to avoid planning full table scans for mutation queries
if any other plan is possible. It now defaults to true.
  • Loading branch information
rytaft committed Dec 19, 2024
1 parent 48274d6 commit 059ef02
Show file tree
Hide file tree
Showing 71 changed files with 2,541 additions and 1,818 deletions.
4 changes: 4 additions & 0 deletions pkg/sql/exec_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3564,6 +3564,10 @@ func (m *sessionDataMutator) SetDisallowFullTableScans(val bool) {
m.data.DisallowFullTableScans = val
}

func (m *sessionDataMutator) SetAvoidFullTableScansInMutations(val bool) {
m.data.AvoidFullTableScansInMutations = val
}

func (m *sessionDataMutator) SetAlterColumnTypeGeneral(val bool) {
m.data.AlterColumnTypeGeneralEnabled = val
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/opt/exec/execbuilder/testdata/autocommit
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ WHERE message LIKE '%r$rangeid: sending batch%'
----
dist sender send r74: sending batch 1 Scan to (n1,s1):1
dist sender send r74: sending batch 1 Put to (n1,s1):1
dist sender send r74: sending batch 1 Scan to (n1,s1):1
dist sender send r74: sending batch 1 Get to (n1,s1):1
dist sender send r74: sending batch 1 EndTxn to (n1,s1):1

query B
Expand Down
37 changes: 37 additions & 0 deletions pkg/sql/opt/exec/execbuilder/testdata/delete
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,9 @@ CREATE TABLE xyz (

# Ensure that we can use a hint to avoid a full table scan.

statement ok
SET avoid_full_table_scans_in_mutations = false

# Without the hint, we plan a full table scan.
query T
EXPLAIN (VERBOSE) DELETE FROM xyz WHERE (y > 0 AND y < 1000) OR (y > 2000 AND y < 3000) RETURNING z
Expand Down Expand Up @@ -375,6 +378,40 @@ vectorized: true
spans: /1-/1000 /2001-/3000
locking strength: for update

# We also avoid the full scan using the session setting
# avoid_full_table_scans_in_mutations.
statement ok
SET avoid_full_table_scans_in_mutations = true

query T
EXPLAIN (VERBOSE) DELETE FROM xyz WHERE (y > 0 AND y < 1000) OR (y > 2000 AND y < 3000) RETURNING z
----
distribution: local
vectorized: true
·
• project
│ columns: (z)
└── • delete
│ columns: (x, z)
│ estimated row count: 990 (missing stats)
│ from: xyz
│ auto commit
└── • index join
│ columns: (x, y, z)
│ estimated row count: 990 (missing stats)
│ table: xyz@xyz_pkey
│ key columns: x
│ locking strength: for update
└── • scan
columns: (x, y)
estimated row count: 990 (missing stats)
table: xyz@xyz_y_idx
spans: /1-/1000 /2001-/3000
locking strength: for update

# Testcase for issue 105803.

statement ok
Expand Down
754 changes: 366 additions & 388 deletions pkg/sql/opt/exec/execbuilder/testdata/explain_redact

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pkg/sql/opt/exec/execbuilder/testdata/schema_change_in_txn
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ query T kvtrace(prefix=/Table/106/)
UPSERT INTO t SELECT a + 1 FROM t
----
Scan /Table/106/{1-2}
Scan /Table/106/{1-2}
Scan /Table/106/1/10{1-2}, /Table/106/1/10{2-3}
Put /Table/106/1/101/0 -> /TUPLE/2:2:Decimal/1000.2/1:3:Bytes/empty
Put /Table/106/1/101/1/1 -> /TUPLE/4:4:Decimal/0.00/2:6:Decimal/1101.2
CPut /Table/106/1/102/0 -> /TUPLE/2:2:Decimal/1000.2/1:3:Bytes/empty
Expand Down
58 changes: 51 additions & 7 deletions pkg/sql/opt/exec/execbuilder/testdata/update
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ CREATE INDEX y_idx ON xyz (y)

# Ensure that we can use a hint to avoid a full table scan.

statement ok
SET avoid_full_table_scans_in_mutations = false

# Without the hint, we plan a full table scan.
query T
EXPLAIN (VERBOSE) UPDATE xyz SET x = 5 WHERE (y > 0 AND y < 1000) OR (y > 2000 AND y < 3000)
Expand Down Expand Up @@ -303,6 +306,45 @@ vectorized: true
spans: /1-/1000 /2001-/3000
locking strength: for update

# We also avoid the full scan using the session setting
# avoid_full_table_scans_in_mutations.
statement ok
SET avoid_full_table_scans_in_mutations = true

query T
EXPLAIN (VERBOSE) UPDATE xyz SET x = 5 WHERE (y > 0 AND y < 1000) OR (y > 2000 AND y < 3000)
----
distribution: local
vectorized: true
·
• update
│ columns: ()
│ estimated row count: 0 (missing stats)
│ table: xyz
│ set: x
│ auto commit
└── • render
│ columns: (x, y, z, x_new)
│ render x_new: 5
│ render x: x
│ render y: y
│ render z: z
└── • index join
│ columns: (x, y, z)
│ estimated row count: 990 (missing stats)
│ table: xyz@xyz_pkey
│ key columns: x
│ locking strength: for update
└── • scan
columns: (x, y)
estimated row count: 990 (missing stats)
table: xyz@y_idx
spans: /1-/1000 /2001-/3000
locking strength: for update

statement ok
CREATE TABLE pks (
k1 INT,
Expand Down Expand Up @@ -359,14 +401,16 @@ vectorized: true
└── • render
└── • top-k
│ order: -v
│ k: 10
└── • limit
│ count: 10
└── • scan
missing stats
table: kv@kv_pkey
spans: FULL SCAN
└── • sort
│ order: -v
└── • scan
missing stats
table: kv@kv_pkey
spans: FULL SCAN

# Use case for UPDATE ... ORDER BY: renumbering a PK without unique violation.
query T
Expand Down
30 changes: 9 additions & 21 deletions pkg/sql/opt/exec/execbuilder/testdata/update_from
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,10 @@ vectorized: true
└── • distinct
│ distinct on: a
└── • hash join
└── • lookup join
│ table: abc@abc_pkey
│ equality: (a) = (a)
│ left cols are key
├── • scan
│ missing stats
│ table: abc@abc_pkey
│ spans: FULL SCAN
│ equality cols are key
└── • scan
missing stats
Expand Down Expand Up @@ -180,14 +176,10 @@ vectorized: true
│ table: ab@ab_pkey
│ spans: FULL SCAN
└── • hash join
└── • lookup join
│ table: abc@abc_pkey
│ equality: (a) = (a)
│ left cols are key
├── • scan
│ missing stats
│ table: abc@abc_pkey
│ spans: FULL SCAN
│ equality cols are key
└── • scan
missing stats
Expand Down Expand Up @@ -226,14 +218,10 @@ vectorized: true
│ table: ab@ab_pkey
│ spans: FULL SCAN
└── • hash join
└── • lookup join
│ table: abc@abc_pkey
│ equality: (a) = (a)
│ left cols are key
├── • scan
│ missing stats
│ table: abc@abc_pkey
│ spans: FULL SCAN
│ equality cols are key
└── • scan
missing stats
Expand Down
55 changes: 55 additions & 0 deletions pkg/sql/opt/exec/execbuilder/testdata/upsert
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,9 @@ vectorized: true
table: indexed@secondary
spans: FULL SCAN

statement ok
SET avoid_full_table_scans_in_mutations = false

query T
EXPLAIN (VERBOSE) UPSERT INTO indexed@{NO_FULL_SCAN} VALUES (1)
----
Expand Down Expand Up @@ -516,6 +519,58 @@ vectorized: true
table: indexed@secondary
spans: FULL SCAN

# We also avoid the full scan using the session setting
# avoid_full_table_scans_in_mutations.
statement ok
SET avoid_full_table_scans_in_mutations = true

query T
EXPLAIN (VERBOSE) UPSERT INTO indexed VALUES (1)
----
distribution: local
vectorized: true
·
• upsert
│ columns: ()
│ estimated row count: 0 (missing stats)
│ into: indexed(a, b, c, d)
│ auto commit
│ arbiter indexes: indexed_pkey
└── • project
│ columns: (column1, b_default, c_default, d_comp, a, b, c, d, b_default, c_default, d_comp, a, check1)
└── • render
│ columns: (check1, column1, b_default, c_default, d_comp, a, b, c, d)
│ render check1: c_default > 0
│ render column1: column1
│ render b_default: b_default
│ render c_default: c_default
│ render d_comp: d_comp
│ render a: a
│ render b: b
│ render c: c
│ render d: d
└── • cross join (left outer)
│ columns: (column1, b_default, c_default, d_comp, a, b, c, d)
│ estimated row count: 1 (missing stats)
├── • values
│ columns: (column1, b_default, c_default, d_comp)
│ size: 4 columns, 1 row
│ row 0, expr 0: 1
│ row 0, expr 1: CAST(NULL AS INT8)
│ row 0, expr 2: 10
│ row 0, expr 3: 11
└── • scan
columns: (a, b, c, d)
estimated row count: 1 (missing stats)
table: indexed@indexed_pkey
spans: /1/0
locking strength: for update

query T
EXPLAIN (VERBOSE)
INSERT INTO indexed@indexed_pkey AS indexed_pk
Expand Down
3 changes: 3 additions & 0 deletions pkg/sql/opt/memo/memo.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ type Memo struct {
intervalStyle duration.IntervalStyle
propagateInputOrdering bool
disallowFullTableScans bool
avoidFullTableScansInMutations bool
largeFullScanRows float64
txnRowsReadErr int64
nullOrderedLast bool
Expand Down Expand Up @@ -248,6 +249,7 @@ func (m *Memo) Init(ctx context.Context, evalCtx *eval.Context) {
intervalStyle: evalCtx.SessionData().GetIntervalStyle(),
propagateInputOrdering: evalCtx.SessionData().PropagateInputOrdering,
disallowFullTableScans: evalCtx.SessionData().DisallowFullTableScans,
avoidFullTableScansInMutations: evalCtx.SessionData().AvoidFullTableScansInMutations,
largeFullScanRows: evalCtx.SessionData().LargeFullScanRows,
txnRowsReadErr: evalCtx.SessionData().TxnRowsReadErr,
nullOrderedLast: evalCtx.SessionData().NullOrderedLast,
Expand Down Expand Up @@ -415,6 +417,7 @@ func (m *Memo) IsStale(
m.intervalStyle != evalCtx.SessionData().GetIntervalStyle() ||
m.propagateInputOrdering != evalCtx.SessionData().PropagateInputOrdering ||
m.disallowFullTableScans != evalCtx.SessionData().DisallowFullTableScans ||
m.avoidFullTableScansInMutations != evalCtx.SessionData().AvoidFullTableScansInMutations ||
m.largeFullScanRows != evalCtx.SessionData().LargeFullScanRows ||
m.txnRowsReadErr != evalCtx.SessionData().TxnRowsReadErr ||
m.nullOrderedLast != evalCtx.SessionData().NullOrderedLast ||
Expand Down
6 changes: 6 additions & 0 deletions pkg/sql/opt/memo/memo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,12 @@ func TestMemoIsStale(t *testing.T) {
evalCtx.SessionData().DisallowFullTableScans = false
notStale()

// Stale avoid full table scan.
evalCtx.SessionData().AvoidFullTableScansInMutations = true
stale()
evalCtx.SessionData().AvoidFullTableScansInMutations = false
notStale()

// Stale large full scan rows.
evalCtx.SessionData().LargeFullScanRows = 1000
stale()
Expand Down
4 changes: 4 additions & 0 deletions pkg/sql/opt/memo/testdata/logprops/delete
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ delete abcde
│ │ │ ├── variable: b:10 [type=int]
│ │ │ └── variable: c:11 [type=int]
│ │ └── const: 1 [type=int]
│ ├── flags: avoid-full-scan
│ ├── key: (13)
│ ├── fd: (13)-->(9-12,14-16), (10,11)-->(12)
│ ├── prune: (9-16)
Expand Down Expand Up @@ -85,6 +86,7 @@ project
│ │ │ ├── variable: b:10 [type=int]
│ │ │ └── variable: c:11 [type=int]
│ │ └── const: 1 [type=int]
│ ├── flags: avoid-full-scan
│ ├── key: (13)
│ ├── fd: (13)-->(9-12,14-16), (10,11)-->(12)
│ ├── prune: (9-16)
Expand Down Expand Up @@ -133,6 +135,7 @@ project
│ │ │ ├── variable: b:10 [type=int]
│ │ │ └── variable: c:11 [type=int]
│ │ └── const: 1 [type=int]
│ ├── flags: avoid-full-scan
│ ├── key: (13)
│ ├── fd: (13)-->(9-12,14-16), (10,11)-->(12)
│ ├── prune: (9-16)
Expand Down Expand Up @@ -178,6 +181,7 @@ project
│ │ │ ├── variable: b:10 [type=int]
│ │ │ └── variable: c:11 [type=int]
│ │ └── const: 1 [type=int]
│ ├── flags: avoid-full-scan
│ ├── key: (13)
│ ├── fd: (13)-->(9-12,14-16), (10,11)-->(12)
│ ├── prune: (9-16)
Expand Down
4 changes: 4 additions & 0 deletions pkg/sql/opt/memo/testdata/logprops/update
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ update abcde
│ │ │ │ │ │ ├── variable: b:10 [type=int]
│ │ │ │ │ │ └── variable: c:11 [type=int]
│ │ │ │ │ └── const: 1 [type=int]
│ │ │ │ ├── flags: avoid-full-scan
│ │ │ │ ├── key: (13)
│ │ │ │ ├── fd: (13)-->(9-12,14-16), (10,11)-->(12)
│ │ │ │ ├── prune: (9-16)
Expand Down Expand Up @@ -141,6 +142,7 @@ project
│ │ │ │ │ │ ├── variable: b:10 [type=int]
│ │ │ │ │ │ └── variable: c:11 [type=int]
│ │ │ │ │ └── const: 1 [type=int]
│ │ │ │ ├── flags: avoid-full-scan
│ │ │ │ ├── key: (13)
│ │ │ │ ├── fd: (13)-->(9-12,14-16), (10,11)-->(12)
│ │ │ │ ├── prune: (9-16)
Expand Down Expand Up @@ -222,6 +224,7 @@ project
│ │ │ │ │ │ ├── variable: b:10 [type=int]
│ │ │ │ │ │ └── variable: c:11 [type=int]
│ │ │ │ │ └── const: 1 [type=int]
│ │ │ │ ├── flags: avoid-full-scan
│ │ │ │ ├── key: (13)
│ │ │ │ ├── fd: (13)-->(9-12,14-16), (10,11)-->(12)
│ │ │ │ ├── prune: (9-16)
Expand Down Expand Up @@ -299,6 +302,7 @@ project
│ │ │ │ │ │ ├── variable: b:10 [type=int]
│ │ │ │ │ │ └── variable: c:11 [type=int]
│ │ │ │ │ └── const: 1 [type=int]
│ │ │ │ ├── flags: avoid-full-scan
│ │ │ │ ├── key: (13)
│ │ │ │ ├── fd: (13)-->(9-12,14-16), (10,11)-->(12)
│ │ │ │ ├── prune: (9-16)
Expand Down
Loading

0 comments on commit 059ef02

Please sign in to comment.