pgconfigurator
pgconfigurator

Subquery Scan

Appears in EXPLAIN asSubquery Scan

Reads the output of a subquery that couldn't be flattened.

What it is

A Subquery Scan reads rows from a sub-SELECT that the planner kept as a separate step instead of pulling up (flattening) into the outer query.

When the planner picks it

When a FROM-clause subquery or view can't be inlined — for example because of DISTINCT, LIMIT, GROUP BY, or volatile functions inside it.

Is it good or bad?

The node itself is nearly free; cost lives in its child. A Subquery Scan that blocks flattening can prevent useful optimizations — sometimes rewriting the subquery lets the planner merge it.

In depth

A fence the planner couldn't open

A Subquery Scan reads rows from a sub-SELECT that the planner kept as its own step instead of pulling up into the outer query. In a typical query the planner flattens SELECT … FROM (SELECT … FROM t) sub into a single plan tree; when it can't (or won't), you get a Subquery Scan.

Common reasons it survives:

  • The subquery has DISTINCT, GROUP BY, LIMIT, or ORDER BY whose meaning would change if flattened.
  • It contains a set-returning function, a volatile function, or a window expression.
  • It's a view defined with one of the above and used without inlining.

The node itself adds essentially no cost; the work is all in its child.

When it blocks an optimization

Sometimes a Subquery Scan prevents a join the planner could otherwise have chosen. Rewriting the subquery into a CTE with NOT MATERIALIZED, or inlining it into the outer query, can let the planner flatten and pick a better join order.

If you suspect this is happening, check whether the subquery contains one of the flattening blockers above and whether they're necessary — LIMIT in a sub-SELECT for example is sometimes redundant once the outer query is considered.

See also