cockroachdb / cockroachdb/cockroach

opt: flag to avoid full scans in mutations is not push across CTE boundary

Open
#144,107 0 comments 0 reactions 0 assignees View on GitHub
C-enhancement T-sql-queries
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.