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
