pgconfigurator
pgconfigurator

Recursive Union

Appears in EXPLAIN asRecursive Union

Drives WITH RECURSIVE CTEs by iterating until no new rows appear.

What it is

A Recursive Union evaluates a WITH RECURSIVE query: it runs the non-recursive term once, then repeatedly runs the recursive term against the previous iteration's rows (via a WorkTable Scan) until it produces nothing new.

When the planner picks it

Only for WITH RECURSIVE common table expressions.

Is it good or bad?

Expected for graph / tree traversals. The danger is runaway recursion — cycles or missing termination conditions — which can balloon the iteration count.

In depth

How a recursive CTE iterates

A Recursive Union drives a WITH RECURSIVE query. It runs the non-recursive term once to produce the starting rows, then repeatedly runs the recursive term — which references the result of the previous step via a WorkTable Scan — until an iteration produces no new rows. Each iteration's output becomes the input for the next.

A typical plan shape:

Recursive Union
  ->  Result                       -- non-recursive (anchor) term
  ->  …                            -- recursive term
        ->  WorkTable Scan on …    -- "rows from the previous step"

Watch out for cycles

If the graph being traversed has cycles and you wrote UNION ALL, the recursion never terminates — the same rows keep getting produced. UNION deduplicates each iteration, which prevents infinite loops at the cost of an extra hash/sort per step.

Either way, defend against runaway recursion with explicit guards:

WITH RECURSIVE walk(id, path) AS (
  SELECT id, ARRAY[id] FROM nodes WHERE id = 1
  UNION ALL
  SELECT n.id, w.path || n.id
  FROM walk w
  JOIN edges e ON e.src = w.id
  JOIN nodes n ON n.id = e.dst
  WHERE n.id <> ALL(w.path)             -- cycle guard
    AND array_length(w.path, 1) < 50    -- depth guard
)
SELECT * FROM walk;

Performance

Recursive CTEs do not benefit from indexes on the working table itself — it's ephemeral. They scale by the work done in each iteration's recursive term. For very wide traversals, materializing intermediate steps into indexed temp tables is sometimes the path forward.

See also