1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-21 05:21:08 +03:00

Teach UNION planner to remove dummy inputs

This adjusts UNION planning so that the planner produces more optimal
plans when one or more of the UNION's subqueries have been proven to be
empty (a dummy rel).

If any of the inputs are empty, then that input can be removed from the
Append / MergeAppend.  Previously, a const-false "Result" node would
appear to represent this.  Removing empty inputs has a few extra
benefits when only 1 union child remains as it means the Append or
MergeAppend can be removed in setrefs.c, making the plan slightly faster
to execute.  Also, we can provide better n_distinct estimates by looking
at the sole remaining input rel's statistics.

Author: David Rowley <dgrowleyml@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAApHDvri53PPF76c3M94_QNWbJfXjyCnjXuj_2=LYM-0m8WZtw@mail.gmail.com
This commit is contained in:
David Rowley
2025-10-04 14:30:03 +13:00
parent 5092aae431
commit 03d40e4b52
3 changed files with 125 additions and 9 deletions

View File

@@ -1216,6 +1216,57 @@ select event_id
drop table events_child, events, other_events;
reset enable_indexonlyscan;
--
-- Test handling of UNION with provably empty inputs
--
-- Ensure the empty UNION input is pruned and de-duplication is done for the
-- remaining relation.
EXPLAIN (COSTS OFF, VERBOSE)
SELECT two FROM tenk1 WHERE 1=2
UNION
SELECT four FROM tenk1
ORDER BY 1;
QUERY PLAN
--------------------------------------
Sort
Output: tenk1.four
Sort Key: tenk1.four
-> HashAggregate
Output: tenk1.four
Group Key: tenk1.four
-> Seq Scan on public.tenk1
Output: tenk1.four
(8 rows)
-- Validate that the results of the above are correct
SELECT two FROM tenk1 WHERE 1=2
UNION
SELECT four FROM tenk1
ORDER BY 1;
two
-----
0
1
2
3
(4 rows)
-- All UNION inputs are proven empty. Ensure the planner provides a
-- const-false Result node
EXPLAIN (COSTS OFF, VERBOSE)
SELECT two FROM tenk1 WHERE 1=2
UNION
SELECT four FROM tenk1 WHERE 1=2
UNION
SELECT ten FROM tenk1 WHERE 1=2;
QUERY PLAN
--------------------------------
Result
Output: unnamed_subquery.two
Replaces: Aggregate
One-Time Filter: false
(4 rows)
-- Test constraint exclusion of UNION ALL subqueries
explain (costs off)
SELECT * FROM

View File

@@ -459,6 +459,33 @@ drop table events_child, events, other_events;
reset enable_indexonlyscan;
--
-- Test handling of UNION with provably empty inputs
--
-- Ensure the empty UNION input is pruned and de-duplication is done for the
-- remaining relation.
EXPLAIN (COSTS OFF, VERBOSE)
SELECT two FROM tenk1 WHERE 1=2
UNION
SELECT four FROM tenk1
ORDER BY 1;
-- Validate that the results of the above are correct
SELECT two FROM tenk1 WHERE 1=2
UNION
SELECT four FROM tenk1
ORDER BY 1;
-- All UNION inputs are proven empty. Ensure the planner provides a
-- const-false Result node
EXPLAIN (COSTS OFF, VERBOSE)
SELECT two FROM tenk1 WHERE 1=2
UNION
SELECT four FROM tenk1 WHERE 1=2
UNION
SELECT ten FROM tenk1 WHERE 1=2;
-- Test constraint exclusion of UNION ALL subqueries
explain (costs off)
SELECT * FROM