Re: Reduce LEFT/FULL JOIN to ANTI JOIN in more cases

From: Richard Guo <guofenglinux(at)gmail(dot)com>
To: wenhui qiu <qiuwenhuifx(at)gmail(dot)com>
Cc: Isaac Morland <isaac(dot)morland(at)gmail(dot)com>, Pg Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: Reduce LEFT/FULL JOIN to ANTI JOIN in more cases
Date: 2026-08-19 06:53:46
Message-ID: CAMbWs4-6FazY7+vCOvR0-vqNuaXOZic8O4D4ZrwMm2woi+Q3uA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I can't help pondering how 0001 collects the quals used to prove a
forced-null Var non-nullable. Pass 1 gathers them into every
subtree's state so that pass 2 doesn't have to re-walk the jointree at
decision time.

Two things bother me about that. First, we already have this
traversal: find_subquery_safe_quals() does the same job for
query_outputs_are_not_nullable(). Two copies with the same rule seems
like something we should avoid. Second, pass 1 builds a list at every
FromExpr and every inner or semi join, for every query containing an
outer join, and each level copies what its children collected, so in a
deep chain of inner joins the same quals get copied over and over on
the way up. What is worse, if there are no forced-null Vars in upper
quals (which is quite common), all of the lists we build in pass 1 are
just wasted.

So I think a better approach is to keep just the jointree node in the
pass 1 state, and have pass 2 call find_subquery_safe_quals() where it
needs the proof. The walk is cheap enough to do on demand.

Attached is a patch showing what I mean.

- Richard

Attachment Content-Type Size
v1-0001-Collect-quals-for-outer-join-reduction-on-demand.patch application/octet-stream 12.3 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Sivirilova Marija 2026-08-19 06:55:53 [PATCH] Fix heap-buffer-overflow in PGTYPEStimestamp_defmt_scan()
Previous Message Anthonin Bonnefoy 2026-08-19 06:50:40 Re: Fix small psql slash option leaks