Redundant outer DISTINCT adds Sort and Unique above EXCEPT

From: 陈列行 <2320415112(at)qq(dot)com>
To: pgsql-hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Redundant outer DISTINCT adds Sort and Unique above EXCEPT
Date: 2026-08-17 08:14:20
Message-ID: tencent_E960DF95B08E1C405C12BBCB485282D6D209@qq.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

## Description

This issue concerns an outer `DISTINCT` applied to an `EXCEPT` result.
Non-`ALL` `EXCEPT` already removes duplicates, so applying `DISTINCT` again
is semantically redundant. PostgreSQL retains the additional operation.

### Expected Behaviour

PostgreSQL should use the duplicate-free property of `EXCEPT` and eliminate
the outer `DISTINCT`. The original and simplified forms should receive
equivalent plans.

### Actual Behaviour

The outer `DISTINCT` adds `Sort -&gt; Unique` above `HashSetOp Except`. With
two 500,000-row inputs and 250,000 result rows, five-run medians were
184.393 ms with the redundant operation and 181.401 ms without it,
approximately 1.6% slower. This timing difference is small enough to overlap
runtime variation, but the extra plan operators are deterministic.

## How to repeat

```sql
DROP TABLE IF EXISTS except_distinct_lhs;
DROP TABLE IF EXISTS except_distinct_rhs;

CREATE TABLE except_distinct_lhs (v INTEGER NOT NULL);
CREATE TABLE except_distinct_rhs (v INTEGER NOT NULL);

INSERT INTO except_distinct_lhs
SELECT g FROM generate_series(1, 500000) AS g;

INSERT INTO except_distinct_rhs
SELECT g FROM generate_series(250001, 750000) AS g;

ANALYZE except_distinct_lhs;
ANALYZE except_distinct_rhs;

EXPLAIN (ANALYZE, BUFFERS, VERBOSE, SETTINGS, TIMING OFF)
SELECT DISTINCT v
FROM (
&nbsp; &nbsp;SELECT v FROM except_distinct_lhs
&nbsp; &nbsp;EXCEPT
&nbsp; &nbsp;SELECT v FROM except_distinct_rhs
) AS set_result;

EXPLAIN (ANALYZE, BUFFERS, VERBOSE, SETTINGS, TIMING OFF)
SELECT v
FROM (
&nbsp; &nbsp;SELECT v FROM except_distinct_lhs
&nbsp; &nbsp;EXCEPT
&nbsp; &nbsp;SELECT v FROM except_distinct_rhs
) AS set_result;
```

Both queries return the same 250,000 rows. The characteristic plans are:

```text
with DISTINCT: Unique -&gt; Sort -&gt; HashSetOp Except
without: &nbsp; &nbsp; &nbsp; HashSetOp Except
```

Browse pgsql-hackers by date

  From Date Subject
Next Message 陈列行 2026-08-17 08:16:39 redundant double negation prevents IN-subquery pull-up and causes a slower SubPlan
Previous Message Hayato Kuroda (Fujitsu) 2026-08-17 08:09:09 RE: Per-table resync for logical replication subscriptions