Hi,

On Thu, 20 Aug 2026 at 11:50, Richard Guo <[email protected]> wrote:

> On Tue, Aug 18, 2026 at 6:22 PM Ayush Tiwari
> <[email protected]> wrote:
> > I tried a case with 1000 unmatched hash tuples where the filter allowed
> > only one through. The executor examined all 1000 and reported "Rows
> > Removed by Filter: 999", while path->rows was one. The patch reduced the
> > cost by 9.99, exactly 999 * cpu_tuple_cost.
> >
> > Could using path->rows therefore undercharge the rows that were examined
> > but filtered out?
>
> Yeah, you're right.  path->rows is the row count after all the quals
> have been applied, while the per-tuple charges here are meant to cover
> the rows that come out of the hash-clause matching, before any other
> quals filter them.
>
> I think a more accurate way is to compute hashjointuples from the
> inner side directly:
>
>   right-semi: inner_path_rows * outer_match_frac
>   right-anti: inner_path_rows * (1 - outer_match_frac)
>
> This is mirroring what JOIN_SEMI and JOIN_ANTI already do with the
> outer side.  Both cpu_tuple_cost and the quals not used for hashing
> are charged on that count, so the 1000 rows your executor examined are
> all charged, and the filter's selectivity affects only the join's
> output row estimate.
>
> Attached v3 patch does that.
>

Thanks for the updated patch, it looks good to me.

Regards,
Ayush

Reply via email to