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-06-10 07:25:25
Message-ID: CAMbWs49Yi+9zvkepkvHrxGken-_7eMUdLVwA1vC5WTa5xeUCpw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Fri, Jun 5, 2026 at 6:33 PM wenhui qiu <qiuwenhuifx(at)gmail(dot)com> wrote:
> Maybe I'm overthinking this, but one implementation detail worth considering
> is whether pass1 should store the derived proof directly, rather than carrying
> the original safe qual lists around.

I considered that. It would give the same answer, but I think
carrying the raw quals is the better deal: pass2 runs
find_nonnullable_vars only when it actually has forced-null vars in
hand, so the common case of outer joins without any IS NULL quals pays
nothing, whereas deriving the set in pass1 would walk every collected
qual for every query containing an outer join.

Also, no qual ever gets walked more than once in pass2: at each
candidate join, the quals its own check consults and the quals pass1
propagates upward are complements (a LEFT join propagates the left
child's quals and consults the right child's, and so on). A qual
consulted by one join therefore never reaches an upper join's proof
set, so pass2 walks each qual at most once. This is the same pruning
correctness requires anyway: quals within a nullable side don't hold
for null-extended rows, and that's exactly the side the join's check
consults.

- Richard

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Chao Li 2026-06-10 07:27:42 Re: [PATCH] Fix typos in pqsignal.c comment
Previous Message Jakub Wartak 2026-06-10 07:24:04 Re: log_postmaster_stats