RE: Plan a filtering inner join as a semijoin

From: William Bernbaum <wbernbaum(at)dwdev(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: "pgsql-hackers(at)lists(dot)postgresql(dot)org" <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: RE: Plan a filtering inner join as a semijoin
Date: 2026-08-26 03:59:37
Message-ID: PH0PR18MB444393A42013D849FC9C68FAA6AE2@PH0PR18MB4443.namprd18.prod.outlook.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Tom,

Fair; completely agreed. In my initial testing, I couldn't overcome a case where pinning a filter rel to the RHS deferred a qual that should have been first. And the selectivity (surely obvious to some; not to me) outweighed any row reduction benefit.

That's why I narrowed it to a single-relation RHS (and gave up the prize - the measured hand-written EXISTS).

One clarification.. not a defense. This isn't quite the reverse of reduce_unique_semijoins(). This only pays when the RHS is not unique.

I think the real defect (but please correct me if I'm wrong) is that it makes a rewrite-time decision about something that should be decided on cost. I came to this conclusion late, but decided to share anyway because I believe there's a path forward.

At a high level: build a second rel; carry it through the join search; let it compete on cost. More optionality for the planner.

-----Original Message-----
From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Sent: Tuesday, August 25, 2026 8:31 PM
To: William Bernbaum <wbernbaum(at)dwdev(dot)com>
Cc: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: Plan a filtering inner join as a semijoin

William Bernbaum <wbernbaum(at)dwdev(dot)com> writes:
> Recently I improved a dynamic SQL compiler (an ORM-like layer) using a
> pattern that seems to generalize to the Postgres planner. I taught
> the layer to emit an EXISTS subquery when the target relation only
> served to filter, rather than fanning out a join whose extra rows were discarded.

> That led me into the join elimination machinery, and to the attached
> draft patch. It adds convert_joins_to_semijoins(), which recognizes
> an inner join that only restricts which rows survive and adds a
> JOIN_SEMI SpecialJoinInfo for the filtering relation.

I find myself a bit astonished by this proposal. Normally we try to convert semijoins to inner joins in order to gain join-order flexibility. I can't see a good reason to go in the other direction.

There might be a reason to install some special case for the query pattern you have in mind, but I really doubt that this particular special case is the best option.

regards, tom lane

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message vignesh C 2026-08-26 04:18:33 Re: Assertion failure in GetSubscriptionRelations() with concurrent DROP TABLE
Previous Message Tom Lane 2026-08-26 03:31:18 Re: Plan a filtering inner join as a semijoin