Parallel-aware nodes (the “Parallel …” prefix)
Appears in EXPLAIN asParallel Seq Scan, Parallel Index Scan, Parallel Hash, …
Worker-cooperating variants of scans, hashes, and appends.
What it is
A 'Parallel ' prefix on a node (Parallel Seq Scan, Parallel Index Scan, Parallel Bitmap Heap Scan, Parallel Hash, Parallel Append, …) means the node cooperates across worker processes — for example, workers divide a table's blocks between them rather than each reading the whole table.
When the planner picks it
Beneath a Gather / Gather Merge, when the planner builds a parallel plan.
Is it good or bad?
These behave like their serial namesakes — the same tuning advice applies. Note that per-node row and timing figures are per-worker averages, which can be confusing when reading the plan. The catalog maps each parallel variant to its base node's page.
In depth
A flag, not a node type
"Parallel-aware" isn't a separate node category — it's a property a node carries. When a Gather (or Gather Merge) launches workers, the nodes beneath it run in each worker, and those that are parallel-aware cooperate across workers so the work is actually divided. The EXPLAIN label is prefixed:
Parallel Seq Scan— workers split the table's blocks between them.Parallel Index Scan/Parallel Index Only Scan— similar, by index range.Parallel Bitmap Heap Scan— workers consume the bitmap together.Parallel Hash— workers cooperatively build one shared hash table for the join.Parallel Append— workers divide the Append's children.Parallel Foreign Scan— only if the FDW implements it.
Nodes inside a parallel subtree that aren't parallel-aware (e.g. a Sort, WindowAgg) still run once per worker, with each worker processing its slice independently.
The two big numerical traps
- Per-loop figures — under a Gather, a child node's
rowsandactual timeare typically per-worker averages, andloopsis the number of participating processes.rows=50000 loops=3processed roughly 150,000 rows in total. work_memis per worker — a parallel Sort or Hash getswork_memfor each participant, so total memory iswork_mem × processes. Raising it without thinking about that multiplies real memory.
When the planner doesn't choose parallelism
Even when a parallel plan exists, the planner may stick with serial because:
- the query's estimated cost is below the parallel-cost thresholds
(
parallel_setup_cost,parallel_tuple_cost); - the table or index portion to scan is below
min_parallel_table_scan_size/min_parallel_index_scan_size; max_parallel_workers_per_gather = 0for the session;- the rest of the plan (a
LIMIT 1, an order it can't preserve) prevents the optimization.
A query that "should be parallel" but isn't usually fails one of those checks, not because parallel mode is disabled.