| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | 2320415112(at)qq(dot)com |
| Subject: | BUG #19567: Redundant outer DISTINCT causes a second full aggregation above UNION |
| Date: | 2026-07-22 06:49:37 |
| Message-ID: | 19567-a99eb73efbfb32fe@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19567
Logged by: cl hl
Email address: 2320415112(at)qq(dot)com
PostgreSQL version: 17.10
Operating system: Linux LAPTOP-2SQAVLB0 6.6.87.2-microsoft-standard-
Description:
## Description
This issue concerns an outer `DISTINCT` applied to a non-`ALL` `UNION`.
`UNION` already returns duplicate-free rows, so the outer operation cannot
alter the result. PostgreSQL nevertheless executes a second full aggregation
over the union output.
### Expected Behaviour
PostgreSQL should propagate the uniqueness guarantee from `UNION` and remove
the outer `DISTINCT`. Both SQL forms should require only the deduplication
performed by `UNION` itself.
### Actual Behaviour
The outer `DISTINCT` adds a second `HashAggregate`. With two 500,000-row
inputs and 750,000 union rows, five-run median execution time increased from
236.234 ms to 420.470 ms. The redundant form is approximately 78.0% slower,
or 1.78x the execution time.
## How to repeat
```sql
DROP TABLE IF EXISTS union_distinct_lhs;
DROP TABLE IF EXISTS union_distinct_rhs;
CREATE TABLE union_distinct_lhs (v INTEGER NOT NULL);
CREATE TABLE union_distinct_rhs (v INTEGER NOT NULL);
INSERT INTO union_distinct_lhs
SELECT g FROM generate_series(1, 500000) AS g;
INSERT INTO union_distinct_rhs
SELECT g FROM generate_series(250001, 750000) AS g;
ANALYZE union_distinct_lhs;
ANALYZE union_distinct_rhs;
EXPLAIN (ANALYZE, BUFFERS, VERBOSE, SETTINGS, TIMING OFF)
SELECT DISTINCT v
FROM (
SELECT v FROM union_distinct_lhs
UNION
SELECT v FROM union_distinct_rhs
) AS set_result;
EXPLAIN (ANALYZE, BUFFERS, VERBOSE, SETTINGS, TIMING OFF)
SELECT v
FROM (
SELECT v FROM union_distinct_lhs
UNION
SELECT v FROM union_distinct_rhs
) AS set_result;
```
Both queries return the same 750,000 rows. The characteristic plans are:
```text
with DISTINCT: HashAggregate -> HashAggregate -> Append
without: HashAggregate -> Append
```
| From | Date | Subject | |
|---|---|---|---|
| Next Message | PG Bug reporting form | 2026-07-22 06:51:33 | BUG #19568: Redundant outer DISTINCT adds Sort and Unique above INTERSECT |
| Previous Message | Amit Kapila | 2026-07-22 06:07:25 | Re: BUG #19556: Segmentation fault in test_decoding |