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, orORDER BYwhose 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.