cockroachdb / cockroachdb/cockroach
opt: flag to avoid full scans in mutations is not push across CTE boundary
- Dominant language
- Go
- Stars
- 32.5k
- Forks
- 4.1k
- PR merge metrics
- PR metrics pending
Description
#137984 added the `avoid-full-scan` flag to scans beneath mutations to reduce contention. For example, notice the `avoid-full-scan` flag in the query plan below:
```sql
CREATE TABLE abc (
a INT PRIMARY KEY,
b INT,
c INT,
INDEX (b)
);
EXPLAIN (OPT, VERBOSE)
UPDATE abc SET c = c + 1 WHERE b = 10 RETURNING a;
-- info
-- ------------------------------------------------------------------
-- update abc
-- ├── columns: a:1
-- ├── fetch columns: a:8 b:9 c:10
-- ├── update-mapping:
-- │ └── c_new:15 => c:3
-- ├── return-mapping:
-- │ └── a:8 => a:1
-- └── project
-- ├── columns: c_new:15 a:8 b:9 c:10
-- ├── index-join abc
-- │ ├── columns: a:8 b:9 c:10
-- │ └── scan abc@abc_b_idx
-- │ ├── columns: a:8 b:9
-- │ ├── constraint: /9/8: [/10 - /10]
-- │ └── flags: avoid-full-scan
-- └── projections
-- └── c:10 + 1 [as=c_new:15, outer=(10), immutable]
```
This flag is not propagated in CTEs. So when the `UPDATE` above is rewritten to use a CTE, a full scan could be selected for the scan:
```sql
EXPLAIN (OPT, VERBOSE)
WITH l AS (
SELECT a FROM abc WHERE b = 10
), d AS (
UPDATE abc SET c = c + 1 WHERE a IN (SELECT a FROM l) RETURNING a
)
SELECT * FROM l;
-- info
-- ------------------------------------------------------------------------------------------------------------
-- with &1 (l)
-- ├── columns: a:25
-- ├── project
-- │ ├── columns: abc.a:1
-- │ └── scan abc@abc_b_idx
-- │ ├── columns: abc.a:1 b:2
-- │ └── constraint: /2/1: [/10 - /10]
-- └── with &2 (d)
-- ├── columns: a:25
-- ├── update abc
-- │ ├── columns: abc.a:8
-- │ ├── fetch columns: abc.a:15 b:16 c:17
-- │ ├── update-mapping:
-- │ │ └── c_new:24 => c:10
-- │ ├── return-mapping:
-- │ │ └── abc.a:15 => abc.a:8
-- │ └── project
-- │ ├── columns: c_new:24 abc.a:15 b:16 c:17
-- │ ├── cost: 65.6800006
-- │ ├── project
-- │ │ ├── columns: abc.a:15 b:16 c:17
-- │ │ └── inner-join (lookup abc)
-- │ │ ├── columns: abc.a:15 b:16 c:17 a:22
-- │ │ ├── key columns: [22] = [15]
-- │ │ ├── with-scan &1 (l)
-- │ │ │ ├── columns: a:22
-- │ │ │ └── mapping:
-- │ │ │ └── abc.a:1 => a:22
-- │ │ └── filters (true)
-- │ └── projections
-- │ └── c:17 + 1 [as=c_new:24, outer=(17), immutable]
-- └── with-scan &1 (l)
-- ├── columns: a:25
-- └── mapping:
-- └── abc.a:1 => a:25
```
Is it safe to push this flag through in all cases?
Jira issue: CRDB-49231
Contributor guide
Research direction
Start by tracing how the avoid-full-scan flag is produced for mutations and represented across the CTE plan shown in the issue. Compare the two EXPLAIN (OPT, VERBOSE) examples and determine which CTE cases can safely preserve the flag; done means the propagation behavior is justified and covered for the relevant cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, sql
- Domain
- backend, databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100