GitHub user Alena0704 closed a discussion: [Ideas] Add ORCA intra-segment
parallel scan support for partitioned AO tables
### Description
> **Preliminary measurements:** These are noisy, uncontrolled measurements
> collected on my laptop with background applications running, not a clean
> benchmark. I plan to repeat the measurements on a virtual machine with a cold
> cache. Treat the timings and speedup ratios below as provisional.
For `SELECT count(*) FROM ao13` over a row-oriented append-optimized table with
13 daily partitions and 6 million rows, ORCA uses a serial `Dynamic Seq Scan`
within each segment even when `enable_parallel=on` and
`max_parallel_workers_per_gather=4`. The PostgreSQL planner produces `Parallel
Append` over `Parallel Seq Scan`. Disabling `optimizer_enable_dynamictablescan`
causes PostgreSQL fallback for this query.
The parallel PostgreSQL plan reduces median execution time from **751.380 to
659.712 ms on unmodified upstream main** (12.2% less time; 1.14× speedup) and
from **713.039 to 649.303 ms on unmodified upstream REL_2_STABLE** (8.9% less
time; 1.10× speedup), with `gp_resqueue_priority=off`. Parallel Append lets
multiple execution participants within each segment share the partition-scan
work, rather than having one participant scan all partitions sequentially. The
measured parallel plans have 12 sending participants across three physical
segments, versus three for ORCA. This distributes scan and partial-aggregation
work across more CPU cores; scheduling overhead, work granularity and host load
limit the resulting speedup. The fallback uses the same PostgreSQL parallel
execution mechanism.
The limitation reproduces on both unmodified upstream branches. This appears to
be a missing capability in ORCA's intra-segment parallel scan support, rather
than a cost-model choice between serial and parallel dynamic scan alternatives.
Parallel execution improves this query's elapsed time in these measurements,
but does not close the performance gap to GP6 on the unmodified builds; the
cross-system comparison is included below.
**Every timing and plan in this report was collected with
`gp_resqueue_priority=off` on the coordinator and all three primary segments.**
Each mode has one warm-up followed by five measured runs. Tables report
execution times in milliseconds; full plans are from measured round 5.
#### Environment and procedure
- Test date: October 14, 2026; macOS arm64 host, 14 logical CPUs, 24 GiB RAM.
- Each cluster has three primary segments on the same host and database
`codex_ao13_verify_20261014`.
- Same table definition, data generation, distribution on `id`, 13 daily
partitions and 6 million rows across builds.
- `gp_resource_manager=queue`, **`gp_resqueue_priority=off`**,
`statement_mem=128000` kB and 16 MiB shared buffers.
- Cloudberry: `max_parallel_workers_per_gather=4`,
`optimizer_disable_dynamic_table_scan=off` in every mode.
- One persistent psql session per build; one warm-up EXPLAIN per mode, then
five measured rounds, with mode order shuffled using seed 1306. Round 0 is
excluded from statistics.
- The build benchmarks ran sequentially. No other benchmarks or builds were
launched by this investigation during measurement. Other host applications
remained running; process-load samples were recorded every two seconds. This is
not an isolated-host benchmark.
- No OS cache flushing was performed. An explicit count was checked once per
mode during warm-up: all benchmark count checks returned **6000000**.
`gp_resqueue_priority` is a startup setting. It was disabled through postgres
startup options on every node, with cluster restart where necessary; it was not
changed using a session SET. The setting was verified on every node (direct
utility connections for the clean Cloudberry clusters; coordinator SHOW plus
distributed pg_settings queries for GP6 and the PR build), and through SHOW in
each benchmark session. The test clusters remain running with this startup
override.
<details>
<summary>Cluster startup option and setting verification</summary>
```text
# Add this option to the existing postgres startup arguments on every node:
-c gp_resqueue_priority=off
```
```sql
SHOW gp_resqueue_priority; -- must report off
```
</details>
The exact restart and sequential measurement procedure is in
[run_priority_off_comparison.py](parallel-partition-verification/analysis/run_priority_off_comparison.py).
Preserve the appropriate dispatch/execute role arguments when restarting nodes.
#### Reproduction SQL
Create and populate this table in each test database where `ao13` does not
already exist:
<details>
<summary>Create, populate and analyze ao13</summary>
```sql
CREATE TABLE ao13 (
id bigint,
d date,
col1 int,
col2 int,
pad text
)
WITH (appendonly=true, orientation=row)
DISTRIBUTED BY (id)
PARTITION BY RANGE (d) (
START ('2020-01-01'::date)
END ('2020-01-14'::date)
EVERY ('1 day'::interval)
);
INSERT INTO ao13
SELECT
g,
'2020-01-01'::date + (g % 13),
g % 97,
g % 89,
repeat('x', 50)
FROM generate_series(1, 6000000) g;
ANALYZE ao13;
```
</details>
The SQL for each optimizer mode accompanies its plan below. In Cloudberry,
disabling `optimizer_enable_dynamictablescan` prevents a specific ORCA
transformation; fallback is verified for this query, not guaranteed for
arbitrary queries. The distinct `optimizer_disable_dynamic_table_scan` remains
`off`. Setting it to `on` enables ORCA's existing dynamic-scan-to-Append
translation, which does not itself provide the parallel alternative described
here.
<details>
<summary>Transaction-scoped fallback reproduction</summary>
```sql
BEGIN;
SET LOCAL optimizer = on;
SET LOCAL optimizer_enable_dynamictablescan = off;
SET LOCAL optimizer_disable_dynamic_table_scan = off;
SET LOCAL enable_parallel = on;
SET LOCAL max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
COMMIT;
```
</details>
#### Cloudberry unmodified upstream main
Source commit `3a586f12c2c2011989734be383ddea69aac24abb`, verified against
upstream main on October 14, 2026. All 19,632 tracked files and symbolic links
matched the commit; no local feature patches or PR #2094 code were applied.
Cloudberry 3.0.0-devel / PostgreSQL 16.9, Apple Clang 21, `--enable-debug
--enable-cassert --enable-orca`, `CFLAGS='-O0 -g'`, `CXXFLAGS='-O0 -g'`.
##### ORCA, parallel on
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = on;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 3:1 (slice1; segments: 3) (actual rows=3 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Dynamic Seq Scan on ao13 (actual rows=2001127 loops=1)
Number of partitions to scan: 13 (out of 13)
Partitions scanned: Avg 13.0 x 3 workers. Max 13 parts
(seg0).
Planning Time: 10.136 ms
(slice0) Executor memory: 114K bytes.
(slice1) Executor memory: 293K bytes avg x 3x(0) workers, 293K bytes max
(seg0).
Memory used: 128000kB
Optimizer: GPORCA
Execution Time: 751.380 ms
```
</details>
### PostgreSQL, parallel off
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = off;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = off;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 3:1 (slice1; segments: 3) (actual rows=3 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Append (actual rows=2001127 loops=1)
-> Seq Scan on ao13_1_prt_1 ao13_1 (actual rows=154105
loops=1)
-> Seq Scan on ao13_1_prt_2 ao13_2 (actual rows=154176
loops=1)
-> Seq Scan on ao13_1_prt_3 ao13_3 (actual rows=154082
loops=1)
-> Seq Scan on ao13_1_prt_4 ao13_4 (actual rows=154188
loops=1)
-> Seq Scan on ao13_1_prt_5 ao13_5 (actual rows=154322
loops=1)
-> Seq Scan on ao13_1_prt_6 ao13_6 (actual rows=154181
loops=1)
-> Seq Scan on ao13_1_prt_7 ao13_7 (actual rows=153987
loops=1)
-> Seq Scan on ao13_1_prt_8 ao13_8 (actual rows=154014
loops=1)
-> Seq Scan on ao13_1_prt_9 ao13_9 (actual rows=153906
loops=1)
-> Seq Scan on ao13_1_prt_10 ao13_10 (actual rows=154053
loops=1)
-> Seq Scan on ao13_1_prt_11 ao13_11 (actual rows=154613
loops=1)
-> Seq Scan on ao13_1_prt_12 ao13_12 (actual rows=154118
loops=1)
-> Seq Scan on ao13_1_prt_13 ao13_13 (actual rows=154235
loops=1)
Planning Time: 1.897 ms
(slice0) Executor memory: 148K bytes.
(slice1) Executor memory: 1962K bytes avg x 3x(0) workers, 1962K bytes
max (seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 759.444 ms
```
</details>
##### PostgreSQL, parallel on
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = off;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 12:1 (slice1; segments: 12) (actual rows=12 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Parallel Append (actual rows=461424 loops=1)
-> Parallel Seq Scan on ao13_1_prt_2 ao13_2 (actual
rows=154176 loops=1)
-> Parallel Seq Scan on ao13_1_prt_3 ao13_3 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_4 ao13_4 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_5 ao13_5 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_6 ao13_6 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_7 ao13_7 (actual
rows=153987 loops=1)
-> Parallel Seq Scan on ao13_1_prt_1 ao13_1 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_8 ao13_8 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_9 ao13_9 (actual
rows=153906 loops=1)
-> Parallel Seq Scan on ao13_1_prt_10 ao13_10 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_11 ao13_11 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_12 ao13_12 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_13 ao13_13 (never
executed)
Planning Time: 2.045 ms
(slice0) Executor memory: 148K bytes.
(slice1) Executor memory: 816K bytes avg x 12x(0) workers, 991K bytes max
(seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 628.481 ms
```
</details>
##### ORCA requested, dynamic scan disabled (fallback)
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = on;
SET optimizer_enable_dynamictablescan = off;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 12:1 (slice1; segments: 12) (actual rows=12 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Parallel Append (actual rows=615803 loops=1)
-> Parallel Seq Scan on ao13_1_prt_2 ao13_2 (actual
rows=154176 loops=1)
-> Parallel Seq Scan on ao13_1_prt_3 ao13_3 (actual
rows=154082 loops=1)
-> Parallel Seq Scan on ao13_1_prt_4 ao13_4 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_5 ao13_5 (actual
rows=154322 loops=1)
-> Parallel Seq Scan on ao13_1_prt_6 ao13_6 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_7 ao13_7 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_1 ao13_1 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_8 ao13_8 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_9 ao13_9 (actual
rows=153906 loops=1)
-> Parallel Seq Scan on ao13_1_prt_10 ao13_10 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_11 ao13_11 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_12 ao13_12 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_13 ao13_13 (never
executed)
Planning Time: 6.685 ms
(slice0) Executor memory: 148K bytes.
(slice1) Executor memory: 816K bytes avg x 12x(0) workers, 991K bytes max
(seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 645.408 ms
```
</details>
#### Cloudberry unmodified upstream REL_2_STABLE
Official apache/cloudberry REL_2_STABLE commit
`2257219513c0e970665f900bdd6ff6e8b49a4d07`, verified against upstream on
October 14, 2026. All 18,935 tracked files and symbolic links matched the
commit; no local feature patches were applied. Cloudberry 2.2.0-incubating /
PostgreSQL 14.10, Apple Clang 21, `--enable-debug --enable-cassert
--enable-orca`, `CFLAGS='-O0 -g'`, `CXXFLAGS='-O0 -g'`.
##### ORCA, parallel on
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = on;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 3:1 (slice1; segments: 3) (actual rows=3 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Dynamic Seq Scan on ao13 (actual rows=2001127 loops=1)
Number of partitions to scan: 13 (out of 13)
Partitions scanned: Avg 13.0 x 3 workers. Max 13 parts
(seg0).
Planning Time: 10.348 ms
(slice0) Executor memory: 114K bytes.
(slice1) Executor memory: 309K bytes avg x 3x(0) workers, 309K bytes max
(seg0).
Memory used: 128000kB
Optimizer: GPORCA
Execution Time: 713.039 ms
```
</details>
##### PostgreSQL, parallel off
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = off;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = off;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 3:1 (slice1; segments: 3) (actual rows=3 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Append (actual rows=2001127 loops=1)
-> Seq Scan on ao13_1_prt_1 ao13_1 (actual rows=154105
loops=1)
-> Seq Scan on ao13_1_prt_2 ao13_2 (actual rows=154176
loops=1)
-> Seq Scan on ao13_1_prt_3 ao13_3 (actual rows=154082
loops=1)
-> Seq Scan on ao13_1_prt_4 ao13_4 (actual rows=154188
loops=1)
-> Seq Scan on ao13_1_prt_5 ao13_5 (actual rows=154322
loops=1)
-> Seq Scan on ao13_1_prt_6 ao13_6 (actual rows=154181
loops=1)
-> Seq Scan on ao13_1_prt_7 ao13_7 (actual rows=153987
loops=1)
-> Seq Scan on ao13_1_prt_8 ao13_8 (actual rows=154014
loops=1)
-> Seq Scan on ao13_1_prt_9 ao13_9 (actual rows=153906
loops=1)
-> Seq Scan on ao13_1_prt_10 ao13_10 (actual rows=154053
loops=1)
-> Seq Scan on ao13_1_prt_11 ao13_11 (actual rows=154613
loops=1)
-> Seq Scan on ao13_1_prt_12 ao13_12 (actual rows=154118
loops=1)
-> Seq Scan on ao13_1_prt_13 ao13_13 (actual rows=154235
loops=1)
Planning Time: 1.919 ms
(slice0) Executor memory: 159K bytes.
(slice1) Executor memory: 1977K bytes avg x 3x(0) workers, 1977K bytes
max (seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 771.687 ms
```
</details>
##### PostgreSQL, parallel on
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = off;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 12:1 (slice1; segments: 12) (actual rows=12 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Parallel Append (actual rows=461612 loops=1)
-> Parallel Seq Scan on ao13_1_prt_2 ao13_2 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_3 ao13_3 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_4 ao13_4 (actual
rows=154188 loops=1)
-> Parallel Seq Scan on ao13_1_prt_5 ao13_5 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_6 ao13_6 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_7 ao13_7 (actual
rows=153987 loops=1)
-> Parallel Seq Scan on ao13_1_prt_1 ao13_1 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_8 ao13_8 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_9 ao13_9 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_10 ao13_10 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_11 ao13_11 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_12 ao13_12 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_13 ao13_13 (never
executed)
Planning Time: 1.894 ms
(slice0) Executor memory: 159K bytes.
(slice1) Executor memory: 831K bytes avg x 12x(0) workers, 1006K bytes
max (seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 701.060 ms
```
</details>
##### ORCA requested, dynamic scan disabled (fallback)
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = on;
SET optimizer_enable_dynamictablescan = off;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 12:1 (slice1; segments: 12) (actual rows=12 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Parallel Append (actual rows=615803 loops=1)
-> Parallel Seq Scan on ao13_1_prt_2 ao13_2 (actual
rows=154176 loops=1)
-> Parallel Seq Scan on ao13_1_prt_3 ao13_3 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_4 ao13_4 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_5 ao13_5 (actual
rows=154322 loops=1)
-> Parallel Seq Scan on ao13_1_prt_6 ao13_6 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_7 ao13_7 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_1 ao13_1 (actual
rows=0 loops=1)
-> Parallel Seq Scan on ao13_1_prt_8 ao13_8 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_9 ao13_9 (actual
rows=153906 loops=1)
-> Parallel Seq Scan on ao13_1_prt_10 ao13_10 (actual
rows=0 loops=1)
-> Parallel Seq Scan on ao13_1_prt_11 ao13_11 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_12 ao13_12 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_13 ao13_13 (never
executed)
Planning Time: 7.737 ms
(slice0) Executor memory: 159K bytes.
(slice1) Executor memory: 831K bytes avg x 12x(0) workers, 1006K bytes
max (seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 681.414 ms
```
</details>
#### Cloudberry 3.0.0-devel + PR #2094
[PR #2094](https://github.com/apache/cloudberry/pull/2094) was an attempt to
address the AO scan performance problem observed in this scenario, so a build
including this PR was also benchmarked. It targets tuple-processing overhead
through lazy attribute extraction; it does not add parallel Dynamic Seq Scan
support.
Main-based PR #2094 test build, source commit
`afbf74172d91cb411752963c9e99dec1e0bc3565`. Cloudberry 3.0.0-devel / PostgreSQL
16.9, Apple Clang 21, assertion-enabled debug build compiled October 10, 2026.
Block size: 8 KiB. Coordinator port 20940, segment ports 20941–20943.
This is not unmodified upstream main. PR #2094 adds lazy AO MemTuple attribute
extraction, which allows `count(*)` to avoid eager tuple deformation. The block
size also differs from the clean builds; the timing difference is not an
isolated measurement of the PR's benefit.
### ORCA, parallel on
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = on;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 3:1 (slice1; segments: 3) (actual rows=3 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Dynamic Seq Scan on ao13 (actual rows=2001127 loops=1)
Number of partitions to scan: 13 (out of 13)
Partitions scanned: Avg 13.0 x 3 workers. Max 13 parts
(seg0).
Planning Time: 9.414 ms
(slice0) Executor memory: 114K bytes.
(slice1) Executor memory: 295K bytes avg x 3x(0) workers, 295K bytes max
(seg0).
Memory used: 128000kB
Optimizer: GPORCA
Execution Time: 491.383 ms
```
</details>
##### PostgreSQL, parallel off
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = off;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = off;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 3:1 (slice1; segments: 3) (actual rows=3 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Append (actual rows=2001127 loops=1)
-> Seq Scan on ao13_1_prt_1 ao13_1 (actual rows=154105
loops=1)
-> Seq Scan on ao13_1_prt_2 ao13_2 (actual rows=154176
loops=1)
-> Seq Scan on ao13_1_prt_3 ao13_3 (actual rows=154082
loops=1)
-> Seq Scan on ao13_1_prt_4 ao13_4 (actual rows=154188
loops=1)
-> Seq Scan on ao13_1_prt_5 ao13_5 (actual rows=154322
loops=1)
-> Seq Scan on ao13_1_prt_6 ao13_6 (actual rows=154181
loops=1)
-> Seq Scan on ao13_1_prt_7 ao13_7 (actual rows=153987
loops=1)
-> Seq Scan on ao13_1_prt_8 ao13_8 (actual rows=154014
loops=1)
-> Seq Scan on ao13_1_prt_9 ao13_9 (actual rows=153906
loops=1)
-> Seq Scan on ao13_1_prt_10 ao13_10 (actual rows=154053
loops=1)
-> Seq Scan on ao13_1_prt_11 ao13_11 (actual rows=154613
loops=1)
-> Seq Scan on ao13_1_prt_12 ao13_12 (actual rows=154118
loops=1)
-> Seq Scan on ao13_1_prt_13 ao13_13 (actual rows=154235
loops=1)
Planning Time: 2.039 ms
(slice0) Executor memory: 149K bytes.
(slice1) Executor memory: 1964K bytes avg x 3x(0) workers, 1964K bytes
max (seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 528.390 ms
```
</details>
##### PostgreSQL, parallel on
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = off;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 12:1 (slice1; segments: 12) (actual rows=12 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Parallel Append (actual rows=461815 loops=1)
-> Parallel Seq Scan on ao13_1_prt_2 ao13_2 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_3 ao13_3 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_4 ao13_4 (actual
rows=154188 loops=1)
-> Parallel Seq Scan on ao13_1_prt_5 ao13_5 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_6 ao13_6 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_7 ao13_7 (actual
rows=153987 loops=1)
-> Parallel Seq Scan on ao13_1_prt_1 ao13_1 (actual
rows=154105 loops=1)
-> Parallel Seq Scan on ao13_1_prt_8 ao13_8 (actual
rows=154014 loops=1)
-> Parallel Seq Scan on ao13_1_prt_9 ao13_9 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_10 ao13_10 (actual
rows=154053 loops=1)
-> Parallel Seq Scan on ao13_1_prt_11 ao13_11 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_12 ao13_12 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_13 ao13_13 (never
executed)
Planning Time: 1.949 ms
(slice0) Executor memory: 149K bytes.
(slice1) Executor memory: 818K bytes avg x 12x(0) workers, 993K bytes max
(seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 494.462 ms
```
</details>
##### ORCA requested, dynamic scan disabled (fallback)
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = on;
SET optimizer_enable_dynamictablescan = off;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 12:1 (slice1; segments: 12) (actual rows=12 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Parallel Append (actual rows=462022 loops=1)
-> Parallel Seq Scan on ao13_1_prt_2 ao13_2 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_3 ao13_3 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_4 ao13_4 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_5 ao13_5 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_6 ao13_6 (actual
rows=154181 loops=1)
-> Parallel Seq Scan on ao13_1_prt_7 ao13_7 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_1 ao13_1 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_8 ao13_8 (actual
rows=154014 loops=1)
-> Parallel Seq Scan on ao13_1_prt_9 ao13_9 (actual
rows=153906 loops=1)
-> Parallel Seq Scan on ao13_1_prt_10 ao13_10 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_11 ao13_11 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_12 ao13_12 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_13 ao13_13 (never
executed)
Planning Time: 6.398 ms
(slice0) Executor memory: 149K bytes.
(slice1) Executor memory: 818K bytes avg x 12x(0) workers, 993K bytes max
(seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 444.927 ms
```
</details>
#### GP6-based OpenGPDB
Installed binary: `PostgreSQL 9.4.26 (Greenplum Database
6.28.8-python+dev.233.g9f785ada8a build dev)`, compiled July 17, 2026 with
Apple Clang 17, `-O0 -g3`, without assertions. This is a GP6-based OpenGPDB
build. Block size: 32 KiB. Coordinator port 21640, segment ports 21641–21643.
The table setup and warm-up/five-run protocol match Cloudberry.
Cloudberry-specific parallel GUCs are not used. Compiler, assertion and
codebase differences prevent interpreting cross-build timings as an isolated
GP6-versus-Cloudberry engine regression.
### ORCA
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = on;
SET optimizer_enable_dynamictablescan = on;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Aggregate (actual rows=1 loops=1)
-> Gather Motion 3:1 (slice1; segments: 3) (actual rows=3 loops=1)
-> Aggregate (actual rows=1 loops=1)
-> Sequence (actual rows=2001127 loops=1)
-> Partition Selector for ao13 (dynamic scan id: 1)
(never executed)
Partitions selected: 13 (out of 13)
-> Dynamic Seq Scan on ao13 (dynamic scan id: 1) (actual
rows=2001127 loops=1)
Partitions scanned: Avg 13.0 (out of 13) x 3
workers. Max 13 parts (seg0).
Planning time: 3.338 ms
(slice0) Executor memory: 67K bytes.
(slice1) Executor memory: 522K bytes avg x 3 workers, 522K bytes max
(seg0).
Memory used: 128000kB
Optimizer: Pivotal Optimizer (GPORCA)
Execution time: 517.615 ms
```
</details>
##### PostgreSQL
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = off;
SET optimizer_enable_dynamictablescan = on;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Aggregate (actual rows=1 loops=1)
-> Gather Motion 3:1 (slice1; segments: 3) (actual rows=3 loops=1)
-> Aggregate (actual rows=1 loops=1)
-> Append (actual rows=2001127 loops=1)
-> Seq Scan on ao13_1_prt_1 (actual rows=154105 loops=1)
-> Seq Scan on ao13_1_prt_2 (actual rows=154176 loops=1)
-> Seq Scan on ao13_1_prt_3 (actual rows=154082 loops=1)
-> Seq Scan on ao13_1_prt_4 (actual rows=154188 loops=1)
-> Seq Scan on ao13_1_prt_5 (actual rows=154322 loops=1)
-> Seq Scan on ao13_1_prt_6 (actual rows=154181 loops=1)
-> Seq Scan on ao13_1_prt_7 (actual rows=153987 loops=1)
-> Seq Scan on ao13_1_prt_8 (actual rows=154014 loops=1)
-> Seq Scan on ao13_1_prt_9 (actual rows=153906 loops=1)
-> Seq Scan on ao13_1_prt_10 (actual rows=154053 loops=1)
-> Seq Scan on ao13_1_prt_11 (actual rows=154613 loops=1)
-> Seq Scan on ao13_1_prt_12 (actual rows=154118 loops=1)
-> Seq Scan on ao13_1_prt_13 (actual rows=154235 loops=1)
Planning time: 0.493 ms
(slice0) Executor memory: 459K bytes.
(slice1) Executor memory: 2027K bytes avg x 3 workers, 2027K bytes max
(seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution time: 479.035 ms
```
</details>
#### Experimental backport of PR #2094 to REL_2_STABLE
PR #2094 snapshot `afbf74172d91cb411752963c9e99dec1e0bc3565` was ported to
upstream REL_2_STABLE commit `2257219513c0e970665f900bdd6ff6e8b49a4d07` in a
separate source tree and cluster. All 11 implementation-file diffs were
applied. Two compatibility adaptations were required: insert
`ri_projectNewNeedsOldTuple` using the PG14 struct layout, and remove the
PG16-only `pg_node_attr(abstract)` annotation. PR expected-output changes were
not imported.
The backend and required extensions were rebuilt cleanly with the same compiler
and debug/assertion configuration as the clean REL_2_STABLE build, with 32 KiB
blocks and 16 MiB shared buffers. Coordinator port 21740; three primary
segments on 21741–21743. `gp_resqueue_priority=off` was verified on all nodes
of both clusters.
**This experimental backport has a reproduced correctness failure in ORCA
UPDATE of an AO table with a stored generated column. It is not a validated
release-ready backport.** The failure and exact reproduction are documented
below; the `count(*)` timings remain a read-only experiment.
### Direct comparison on REL_2_STABLE
The clean baseline and patched cluster were benchmarked sequentially after
compilation and targeted checks finished, each using the same table setup, one
warm-up and five measured runs per mode. All eight explicit count checks
returned **6000000**. This dedicated comparison has its own clean-baseline
measurements; use the two columns below together. The laptop/background-load
qualification at the start of this issue also applies here.
| Mode | Clean REL_2_STABLE median, ms | REL_2_STABLE + PR #2094 median, ms |
Speedup | Execution-time reduction |
| --- | ---: | ---: | ---: | ---: |
| ORCA, parallel on | 737.715 | 502.429 | 1.47× | 31.9% |
| PostgreSQL, parallel off | 783.095 | 546.616 | 1.43× | 30.2% |
| PostgreSQL, parallel on | 612.403 | 420.974 | 1.45× | 31.3% |
| ORCA requested, dynamic scan disabled (fallback) | 645.757 | 423.416 | 1.53×
| 34.4% |
| Build / mode | Five measured runs, ms |
| --- | --- |
| Clean REL_2_STABLE: ORCA, parallel on | 1297.874, 1055.004, 737.715, 718.399,
717.628 |
| Clean REL_2_STABLE: PostgreSQL, parallel off | 1300.733, 790.665, 757.807,
783.095, 735.744 |
| Clean REL_2_STABLE: PostgreSQL, parallel on | 1160.053, 659.687, 600.154,
584.615, 612.403 |
| Clean REL_2_STABLE: ORCA requested, dynamic scan disabled (fallback) |
1221.777, 513.941, 615.064, 645.757, 646.302 |
| Experimental backport: ORCA, parallel on | 499.034, 502.429, 490.401,
526.339, 511.780 |
| Experimental backport: PostgreSQL, parallel off | 554.047, 545.989, 546.616,
512.422, 553.171 |
| Experimental backport: PostgreSQL, parallel on | 425.496, 409.458, 420.974,
422.405, 412.598 |
| Experimental backport: ORCA requested, dynamic scan disabled (fallback) |
461.747, 455.063, 388.207, 423.416, 385.274 |
The ORCA plan remains `Dynamic Seq Scan`; PostgreSQL parallel and fallback
retain `Parallel Append`. This is an AO tuple-processing improvement, not
parallel Dynamic Seq Scan support. The baseline's first measured round was
noticeably slower than subsequent rounds, so these provisional laptop timings
should not be treated as a precise production speedup.
##### Experimental backport: query SQL and complete plans
##### ORCA, parallel on
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = on;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 3:1 (slice1; segments: 3) (actual rows=3 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Dynamic Seq Scan on ao13 (actual rows=2001127 loops=1)
Number of partitions to scan: 13 (out of 13)
Partitions scanned: Avg 13.0 x 3 workers. Max 13 parts
(seg0).
Planning Time: 9.067 ms
(slice0) Executor memory: 114K bytes.
(slice1) Executor memory: 311K bytes avg x 3x(0) workers, 311K bytes max
(seg0).
Memory used: 128000kB
Optimizer: GPORCA
Execution Time: 511.780 ms
```
</details>
##### PostgreSQL, parallel off
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = off;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = off;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 3:1 (slice1; segments: 3) (actual rows=3 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Append (actual rows=2001127 loops=1)
-> Seq Scan on ao13_1_prt_1 ao13_1 (actual rows=154105
loops=1)
-> Seq Scan on ao13_1_prt_2 ao13_2 (actual rows=154176
loops=1)
-> Seq Scan on ao13_1_prt_3 ao13_3 (actual rows=154082
loops=1)
-> Seq Scan on ao13_1_prt_4 ao13_4 (actual rows=154188
loops=1)
-> Seq Scan on ao13_1_prt_5 ao13_5 (actual rows=154322
loops=1)
-> Seq Scan on ao13_1_prt_6 ao13_6 (actual rows=154181
loops=1)
-> Seq Scan on ao13_1_prt_7 ao13_7 (actual rows=153987
loops=1)
-> Seq Scan on ao13_1_prt_8 ao13_8 (actual rows=154014
loops=1)
-> Seq Scan on ao13_1_prt_9 ao13_9 (actual rows=153906
loops=1)
-> Seq Scan on ao13_1_prt_10 ao13_10 (actual rows=154053
loops=1)
-> Seq Scan on ao13_1_prt_11 ao13_11 (actual rows=154613
loops=1)
-> Seq Scan on ao13_1_prt_12 ao13_12 (actual rows=154118
loops=1)
-> Seq Scan on ao13_1_prt_13 ao13_13 (actual rows=154235
loops=1)
Planning Time: 1.879 ms
(slice0) Executor memory: 161K bytes.
(slice1) Executor memory: 1978K bytes avg x 3x(0) workers, 1978K bytes
max (seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 553.171 ms
```
</details>
##### PostgreSQL, parallel on
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = off;
SET optimizer_enable_dynamictablescan = on;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 12:1 (slice1; segments: 12) (actual rows=12 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Parallel Append (actual rows=462022 loops=1)
-> Parallel Seq Scan on ao13_1_prt_2 ao13_2 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_3 ao13_3 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_4 ao13_4 (actual
rows=154188 loops=1)
-> Parallel Seq Scan on ao13_1_prt_5 ao13_5 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_6 ao13_6 (actual
rows=154181 loops=1)
-> Parallel Seq Scan on ao13_1_prt_7 ao13_7 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_1 ao13_1 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_8 ao13_8 (actual
rows=154014 loops=1)
-> Parallel Seq Scan on ao13_1_prt_9 ao13_9 (actual
rows=153906 loops=1)
-> Parallel Seq Scan on ao13_1_prt_10 ao13_10 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_11 ao13_11 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_12 ao13_12 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_13 ao13_13 (never
executed)
Planning Time: 1.779 ms
(slice0) Executor memory: 161K bytes.
(slice1) Executor memory: 833K bytes avg x 12x(0) workers, 1008K bytes
max (seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 412.598 ms
```
</details>
##### ORCA requested, dynamic scan disabled (fallback)
<details>
<summary>Reproduction SQL</summary>
```sql
SET optimizer = on;
SET optimizer_enable_dynamictablescan = off;
SET optimizer_disable_dynamic_table_scan = off;
SET enable_parallel = on;
SET max_parallel_workers_per_gather = 4;
EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF)
SELECT count(*) FROM ao13;
```
</details>
<details>
<summary>Query execution plan — measured round 5</summary>
```text
Finalize Aggregate (actual rows=1 loops=1)
-> Gather Motion 12:1 (slice1; segments: 12) (actual rows=12 loops=1)
-> Partial Aggregate (actual rows=1 loops=1)
-> Parallel Append (actual rows=461625 loops=1)
-> Parallel Seq Scan on ao13_1_prt_2 ao13_2 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_3 ao13_3 (actual
rows=154082 loops=1)
-> Parallel Seq Scan on ao13_1_prt_4 ao13_4 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_5 ao13_5 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_6 ao13_6 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_7 ao13_7 (actual
rows=153987 loops=1)
-> Parallel Seq Scan on ao13_1_prt_1 ao13_1 (actual
rows=154105 loops=1)
-> Parallel Seq Scan on ao13_1_prt_8 ao13_8 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_9 ao13_9 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_10 ao13_10 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_11 ao13_11 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_12 ao13_12 (never
executed)
-> Parallel Seq Scan on ao13_1_prt_13 ao13_13 (never
executed)
Planning Time: 6.076 ms
(slice0) Executor memory: 161K bytes.
(slice1) Executor memory: 833K bytes avg x 12x(0) workers, 1008K bytes
max (seg0).
Memory used: 128000kB
Optimizer: Postgres query optimizer
Execution Time: 385.274 ms
```
</details>
##### Correctness checks and known failure
With ORCA requested, 14 targeted assertions passed before the
stored-generated-column UPDATE assertion failed. These checks cover wide rows,
NULLs, arrays, large text, partial and late attribute reads,
sort/materialization, index lookup, ordinary and distribution-key UPDATE,
VACUUM compaction, column-layout changes and table rewrite. Some operations use
PostgreSQL fallback, as recorded in the logs. The PostgreSQL-planner run
completed all 16 assertions. These targeted checks are not a full regression
suite.
A separate transaction-scoped reproduction confirmed the difference:
| Build / requested optimizer | Actual UPDATE optimizer | Rows with incorrect
generated value |
| --- | --- | ---: |
| Clean REL_2_STABLE / ORCA | PostgreSQL fallback | 0 / 100 |
| Clean REL_2_STABLE / PostgreSQL | PostgreSQL | 0 / 100 |
| Experimental backport / ORCA | GPORCA | **100 / 100** |
| Experimental backport / PostgreSQL | PostgreSQL | 0 / 100 |
For example, the row `(id=1, a=1, b=2)` becomes `(id=1, a=2, b=2)` under the
patched ORCA UPDATE, although `b` should become 4. The experiment establishes a
regression in this backport; it does not establish the behavior of the same
case on upstream main.
<details>
<summary>Stored generated column UPDATE reproduction</summary>
```sql
\set ON_ERROR_STOP on
SET optimizer = on;
BEGIN;
CREATE TABLE public.backport_generated_check (id int, a int, b int GENERATED
ALWAYS AS (a*2) STORED) USING ao_row DISTRIBUTED BY(id);
INSERT INTO public.backport_generated_check (id,a) SELECT g,g FROM
generate_series(1,100) g;
EXPLAIN (COSTS OFF) UPDATE public.backport_generated_check SET a=a+1;
UPDATE public.backport_generated_check SET a=a+1;
SELECT count(*) AS rows, count(*) FILTER (WHERE b IS DISTINCT FROM a*2) AS
incorrect_generated_values FROM public.backport_generated_check;
SELECT * FROM public.backport_generated_check WHERE b IS DISTINCT FROM a*2
ORDER BY id LIMIT 5;
ROLLBACK;
```
</details>
Artifacts: [backport
patch](parallel-partition-verification/rel2-pr2094/rel2-pr2094-backport.patch),
[compatibility
notes](parallel-partition-verification/rel2-pr2094/backport-notes.txt), [build
procedure](parallel-partition-verification/rel2-pr2094/build.sh), [comparison
runner](parallel-partition-verification/rel2-pr2094/run-comparison.py),
[clean-baseline
plans](parallel-partition-verification/rel2/ab-pr2094/benchmark.log),
[clean-baseline
measurements](parallel-partition-verification/rel2/ab-pr2094/results.json),
[backport plans](parallel-partition-verification/rel2-pr2094/benchmark.log),
[backport
measurements](parallel-partition-verification/rel2-pr2094/results.json),
[targeted SQL](parallel-partition-verification/rel2-pr2094/targeted.sql), [ORCA
test log](parallel-partition-verification/rel2-pr2094/logs/targeted-on.log),
[PostgreSQL test
log](parallel-partition-verification/rel2-pr2094/logs/targeted-off.log),
[generated-column failure log](parallel-partition-verification/rel2-
pr2094/logs/generated-21740-on.log).
#### Interpretation
All tested modes returned the expected count of 6,000,000 rows. ORCA used a
serial Dynamic Seq Scan on both upstream branches, while the PostgreSQL planner
produced Parallel Append.
#### Expected Cloudberry behavior
When parallel execution is enabled and safe, ORCA should be able to consider a
parallel alternative for scanning partitioned AO tables and choose it when
justified by cost.
The required outcome is parallel work distribution without changing query
results or partition-pruning semantics. This could be implemented as a
parallel-aware DynamicSeqScan or an appropriate Parallel Append plan; a
particular plan-node representation is not required by this report.
#### Cloudberry code investigation
The following observations come from inspection of the local Cloudberry
checkout:
1. `src/backend/gporca/libgpopt/src/xforms/CXformGet2ParallelTableScan.cpp`
matches `CLogicalGet`. There is no corresponding parallel implementation
transformation among the candidates in `CLogicalDynamicGet::PxfsCandidates()`.
2. `src/backend/executor/nodeDynamicSeqscan.c` advances a local `whichPart`
counter, opens a partition, and initializes its ordinary SeqScan through
`ExecInitSeqScanForPartition()`. This does not distribute partitions between
workers.
3. `src/backend/executor/execParallel.c` handles SeqScan and Append in its MPP
DSM walkers, but has no DynamicSeqScanState handler.
4. `CTranslatorDXLToPlStmt::ExtractParallelWorkersFromDXL()` in
`src/backend/gpopt/translate/CTranslatorDXLToPlStmt.cpp` treats
`EdxlopPhysicalDynamicTableScan` as a non-parallel scan and returns degree 1.
5. `src/backend/gpopt/config/CConfigParamMapping.cpp` maps
`optimizer_enable_dynamictablescan = off` to disabling
`ExfDynamicGet2DynamicTableScan`, explaining the fallback observed for this
query.
##### Potential implementation directions
For a parallel-aware DynamicSeqScan, a shared partition queue/counter could
distribute whole partitions among workers within each segment. This would
require coordinated partition-pruning results, DSM initialization and worker
attachment, correct rescan behavior, and corresponding
ORCA/DXL/plan-translation support. The ORCA implementation must also account
for worker distribution, rewindability, and cost.
Whole-partition scheduling is a limited first step: it cannot parallelize a
scan when pruning leaves only one partition. Sharing work within a partition
would require additional support.
AO scan granularity also matters. In the inspected
`src/backend/access/appendonly/appendonlyam.c`, parallel work allocation uses
AO segment-file indexes. The number and sizes of readable AO files can limit
effective parallelism even when a plan contains Parallel Seq Scan nodes.
An alternative is to extend ORCA's existing dynamic-scan-to-Append translation
to generate a valid parallel plan and reuse the Parallel Append executor
infrastructure.
#### Related discussions and PRs
- [Discussion #1316 — Enhanced ORCA Parallel Planning to Align with PostgreSQL
Planner](https://github.com/apache/cloudberry/discussions/1316): the broader
proposal for closing the parallel-planning gap between ORCA and the PostgreSQL
planner. PR #1398 is identified as its first milestone.
- [PR #1398 — implement intra-segment parallel table scan
support](https://github.com/apache/cloudberry/pull/1398), merged May 13, 2026:
introduces `CPhysicalParallelTableScan`, `CXformGet2ParallelTableScan`, worker
distribution, cost-model integration, and DXL support. Its description
explicitly excludes dynamic scans from the supported scope.
- [PR #1022 — ORCA: allow partition table use the append
node](https://github.com/apache/cloudberry/pull/1022), merged June 25, 2025:
related to the existing Append translation and
`optimizer_disable_dynamic_table_scan` setting. It is relevant to an
alternative implementation direction, but does not itself resolve this
parallel-planning gap in the inspected code.
- [PR #647 — Refactor parallel scan node and
framework](https://github.com/apache/cloudberry/pull/647), merged October 16,
2024: establishes the unified MPP DSM initialization approach for parallel scan
nodes.
- [PR #1512 — Fix assertion failure for dynamic table scan
rewindability](https://github.com/apache/cloudberry/pull/1512), merged December
29, 2025: relevant to preserving correct physical properties when extending
DynamicTableScan.
- [PR #1452 — [WIP] Orca
parallel](https://github.com/apache/cloudberry/pull/1452): closed without
merging; included as related historical work, not an available fix.
#### Suggested validation for a fix
- Confirm `count(*) = 6000000` with ORCA parallel execution enabled and
disabled, and with the PostgreSQL planner.
- Verify that ORCA can produce a parallel partition scan when the alternative
is safe and cost-effective.
- Cover static pruning, dynamic pruning, no matching partitions, one matching
partition, and multiple partitions.
- Exercise rescans and parameter changes where supported, or verify that
unsupported plan shapes are correctly rejected.
- Check partitions with different column layouts, empty partitions, uneven
partition sizes, and different AO segment-file counts.
- Measure repeated runs under documented cache and build conditions; keep
correctness and plan-shape checks separate from performance claims.
#### Final comparison — gp_resqueue_priority=off on every node
All rows use one warm-up and five measured runs; median excludes warm-up.
| System | Mode | Actual scan | Run 5 execution, ms | Median execution, ms |
| --- | --- | --- | ---: | ---: |
| Cloudberry unmodified upstream main | ORCA, parallel on | Dynamic Seq Scan |
751.380 | 751.380 |
| Cloudberry unmodified upstream main | PostgreSQL, parallel off | Append |
759.444 | 759.444 |
| Cloudberry unmodified upstream main | PostgreSQL, parallel on | Parallel
Append | 628.481 | 659.712 |
| Cloudberry unmodified upstream main | ORCA requested, dynamic scan disabled
(fallback) | Parallel Append | 645.408 | 668.949 |
| Cloudberry unmodified upstream REL_2_STABLE | ORCA, parallel on | Dynamic Seq
Scan | 713.039 | 713.039 |
| Cloudberry unmodified upstream REL_2_STABLE | PostgreSQL, parallel off |
Append | 771.687 | 782.740 |
| Cloudberry unmodified upstream REL_2_STABLE | PostgreSQL, parallel on |
Parallel Append | 701.060 | 649.303 |
| Cloudberry unmodified upstream REL_2_STABLE | ORCA requested, dynamic scan
disabled (fallback) | Parallel Append | 681.414 | 614.259 |
| Cloudberry 3.0.0-devel + PR #2094 | ORCA, parallel on | Dynamic Seq Scan |
491.383 | 476.438 |
| Cloudberry 3.0.0-devel + PR #2094 | PostgreSQL, parallel off | Append |
528.390 | 517.919 |
| Cloudberry 3.0.0-devel + PR #2094 | PostgreSQL, parallel on | Parallel Append
| 494.462 | 378.813 |
| Cloudberry 3.0.0-devel + PR #2094 | ORCA requested, dynamic scan disabled
(fallback) | Parallel Append | 444.927 | 443.250 |
| GP6-based OpenGPDB | ORCA | Dynamic Seq Scan | 517.615 | 442.338 |
| GP6-based OpenGPDB | PostgreSQL | Append | 479.035 | 461.166 |
| REL_2_STABLE + PR #2094 (experimental; known UPDATE failure) | ORCA, parallel
on | Dynamic Seq Scan | 511.780 | 502.429 |
| REL_2_STABLE + PR #2094 (experimental; known UPDATE failure) | PostgreSQL,
parallel off | Append | 553.171 | 546.616 |
| REL_2_STABLE + PR #2094 (experimental; known UPDATE failure) | PostgreSQL,
parallel on | Parallel Append | 412.598 | 420.974 |
| REL_2_STABLE + PR #2094 (experimental; known UPDATE failure) | ORCA
requested, dynamic scan disabled (fallback) | Parallel Append | 385.274 |
423.416 |
The experimental backport has a dedicated paired baseline and known correctness
failure documented above.
##### Execution time relative to GP6
The reference medians are **442.338 ms for GP6 ORCA** and **461.166 ms for the
GP6 PostgreSQL planner**. The table shows **Cloudberry execution time / GP6
execution time**: a ratio above 1 means Cloudberry took longer; a ratio below 1
means it took less time.
ORCA is compared with GP6 ORCA. All PostgreSQL execution modes, including ORCA
fallback, are compared with the GP6 PostgreSQL planner. GP6 uses serial Append,
so the parallel columns compare the available execution strategies rather than
identical plan shapes.
| Cloudberry build | ORCA / GP6 ORCA | PostgreSQL serial / GP6 PostgreSQL |
PostgreSQL parallel / GP6 PostgreSQL | Fallback / GP6 PostgreSQL |
| --- | ---: | ---: | ---: | ---: |
| Unmodified upstream main | 1.70× | 1.65× | 1.43× | 1.45× |
| Unmodified upstream REL_2_STABLE | 1.61× | 1.70× | 1.41× | 1.33× |
| 3.0.0-devel + PR #2094 | 1.08× | 1.12× | 0.82× | 0.96× |
| REL_2_STABLE + PR #2094 (experimental; known UPDATE failure) | 1.14× | 1.19×
| 0.91× | 0.92× |
In these measurements, unmodified main and REL_2_STABLE took **1.70× and 1.61×
as long as GP6 with ORCA**, respectively. Even with PostgreSQL Parallel Append,
they took **1.43× and 1.41× as long as the GP6 PostgreSQL planner**. The PR
#2094 builds narrow the ORCA gap and show lower median times than GP6 in the
PostgreSQL parallel mode.
These are provisional laptop measurements with the build differences documented
above, not an isolated cross-version regression measurement. The experimental
REL_2_STABLE backport also has a known UPDATE correctness failure.
Patch that I used for measures REL_2_STABLE + #2094 attached as a file.
[rel2-pr2094-backport.patch](https://github.com/user-attachments/files/33438658/rel2-pr2094-backport.patch)
### Related issues
[Add ORCA intra-segment parallel scan support for partitioned AO
tables](https://github.com/apache/cloudberry/issues/2129)
### Are you willing to submit a PR?
- [ ] Yes I am willing to submit a PR!
GitHub link: https://github.com/apache/cloudberry/discussions/2128
----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to: [email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]