Enable parallel VACUUM (currently disabled via GPDB_14_MERGE_FIXME due to lock issues)
- Dominant language
- C
- Stars
- 1.4k
- Forks
- 247
- Avg merge
- 4d 3h
- Merged PRs (30d)
- 39
Description
## Summary
PostgreSQL 16's **parallel `VACUUM`** (parallel index vacuuming) is currently **disabled** in Cloudberry. `VACUUM (PARALLEL n)` is accepted syntactically, but at runtime the parallel option is silently downgraded to serial with a `WARNING`, on both the coordinator and every segment. The real parallel code path is compiled out.
## Where
`src/backend/access/heap/vacuumlazy.c:3209`
```c
/* GPDB_14_MERGE_FIXME: Don't support parallel vacuum now, we need to fix lock issues. */
if (nworkers > 0 && vacrel->do_index_vacuuming && vacrel->nindexes > 1)
ereport(WARNING,
(errmsg("disabling parallel option of vacuum on \"%s\" --- cannot vacuum tables in parallel",
vacrel->relname)));
#if 0
else
... /* the actual parallel_vacuum_init() / parallel path is #if 0'd out */
```
So any table with more than one index that is asked to vacuum in parallel hits this guard, and the upstream parallel path below it is dead-coded via `#if 0`.
## Reproduction
Environment: PostgreSQL 16.9 / Apache Cloudberry 3.0.0-devel (`main`, `c781604c5bad`), 3 primary segments.
```sql
CREATE TABLE pv_demo(id int, a int, b int, c text) DISTRIBUTED BY (id);
INSERT INTO pv_demo SELECT g,g,g,md5(g::text) FROM generate_series(1,1000000) g;
CREATE INDEX ON pv_demo(a);
CREATE INDEX ON pv_demo(b);
CREATE INDEX ON pv_demo(c);
DELETE FROM pv_demo WHERE id % 3 = 0;
VACUUM (PARALLEL 3, VERBOSE) pv_demo;
```
Output:
```
WARNING: disabling parallel option of vacuum on "pv_demo" --- cannot vacuum tables in parallel
WARNING: disabling parallel option of vacuum on "pv_demo" --- cannot vacuum tables in parallel (seg0 ... )
WARNING: disabling parallel option of vacuum on "pv_demo" --- cannot vacuum tables in parallel (seg1 ... )
WARNING: disabling parallel option of vacuum on "pv_demo" --- cannot vacuum tables in parallel (seg2 ... )
INFO: finished vacuuming "postgres.public.pv_demo": index scans: 1
```
The vacuum completes, but serially (`index scans: 1`, no parallel workers launched).
## Root cause
Per the in-tree comment, parallel vacuum was left disabled during the PG14→PG16 merge because of unresolved **lock issues** in the MPP context (parallel workers inside a QE backend vs. the segment-local locking / dispatch model). The parallel path was `#if 0`'d rather than adapted.
## Proposed work
1. Resolve the lock issues that block backend-parallel index vacuuming inside a segment QE.
2. Re-enable the `#if 0`'d parallel path (`parallel_vacuum_init()` etc.) so `VACUUM (PARALLEL n)` and autovacuum can use parallel workers per segment.
3. If it cannot be supported in the MPP model, replace the silent runtime downgrade with clear documentation and, ideally, a one-time notice rather than a per-relation `WARNING`.
## Notes
- `max_parallel_maintenance_workers` currently defaults to `2` but has no effect on VACUUM because of the guard above.
- Scope: heap tables with 2+ indexes. AO/AOCO tables use a different vacuum path and are out of scope for this specific guard.
Contributor guide
Assessment
This issue has not been assessed yet.