Skip to content
In this guide

Guide · The plan, node by node

Gather

A Gather sits above the parallel part of a plan, starts the workers, and collects their rows into one stream. Gather Merge does the same for sorted input, so the order survives. Under a Gather the leader and each worker run their own copy of the nodes below. The sample ran with max_parallel_workers_per_gather = 0, so its plan has no Gather. At the default of 2, the Seq Scan on commerce.orders would become a Parallel Seq Scan under a Gather, with three processes sharing the 183,000 pages.

Why it matters

Parallelism helps a big scan or aggregate that is bound by CPU. It helps less when the scan is bound by disk, as the sample's was, with 181,796 of 183,000 pages read from outside the cache. Check Workers Planned against Workers Launched. Workers come from a pool shared by the whole server, max_parallel_workers, and when other queries hold them the Gather starts with fewer than planned, or none. A plan costed for three processes then runs on one, slower than the serial plan the planner would have chosen. Rows under a Gather are per process. Loops has the arithmetic.

What to do

  1. If Workers Launched is below Workers Planned, look at what else was running. max_worker_processes and max_parallel_workers cap the pool.
  2. If the parallel plan is slower than the serial one, SET max_parallel_workers_per_gather = 0 for one run gives you the serial plan to compare.
  3. min_parallel_table_scan_size is 8MB by default. Smaller tables never get a Gather, on purpose.

In the Plan tab

Parallel-aware nodes are labelled Parallel Seq Scan, and the Gather joins their bands into one. The finding Fewer workers launched, N of M parallel workers, fires when the launch fell short. A band's estimate is the planner's rows per process times the workers planned plus one.

Last checked against Seqora 0.3.2, PostgreSQL 17 on .

Found a bug, missing a feature, or just curious? Write to me. Every email lands in my own inbox, not a ticket queue.