| From: | Andrei Lepikhov <lepihov(at)gmail(dot)com> |
|---|---|
| To: | Tomas Vondra <tomas(at)vondra(dot)me>, Matheus Alcantara <matheusssilv97(at)gmail(dot)com>, Andrew Dunstan <andrew(at)dunslane(dot)net>, PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org> |
| Subject: | Re: hashjoins vs. Bloom filters (yet again) |
| Date: | 2026-09-02 18:12:49 |
| Message-ID: | c08f8403-bbf5-43b0-bb3c-c8d4524d9304@gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
On 22/08/2026 00:26, Tomas Vondra wrote:
As I see it, the bottom-up, cost-based approach quickly becomes complicated, and
two of the underlying problems look fundamental.
1. Estimating the number of unmatched rows. This is the key input to the
filter's cost model, and I don't see a way to implement it. We do have
eqjoinsel_semi(), but it compares MCV lists and then assumes uniformity over
n_distinct for everything else — and the unmatched rows live mostly in that
tail. So it is not that the estimate is imprecise; for the part of the
population that decides the answer, there is no distribution model at all, only
a count of distinct values. Histogram-based join estimation, of the kind GPORCA
does by aligning buckets, does not exist here. That is one more piece of basic
technology we would need first.
Systems that ship this feature don't really solve it either — they work around
it. The CIDR 2026 paper [1] on bitmap filters in SQL Server describes an
optimiser that decides on the filter from ordinary join selectivity, then defers
the bitmap's shape and memory budget to run time. That is adaptation, not
estimation.
2. Path propagation. Filtered paths seem to need planning as parameterised ones.
That may well be doable. However, the use case is narrow compared with the
growth of the search space it brings for complex queries, and the effect is not
local: once filters are in the optimiser, the best join order itself changes [2].
Hence, unblocking the bottom-up route means solving both of these in advance,
and I don't see either one coming any closer.
Meanwhile, as the v2 patch [3] shows, the opportunistic approach can plausibly
satisfy 'do better or the same'. Its open questions — how to represent the cost
in EXPLAIN, how to decide adaptively whether to enable the filter, the overhead
in parallel plans — are real, but none of them blocks the design the way the two
above do.
What it buys: simple code and zero overhead at planning time. Also, I don't read
these as competing designs. The opportunistic path can go in now and collect the
field experience the bottom-up one is currently missing.
I ran a v2-modified instance under a real-life ORM load. Besides the positive
changes in execution time, it turned up something I did not expect: the filter
makes visible those cases where one more index, on one side of the join clause
expression, would switch a heavy HashJoin into a fast parameterised NestLoop.
I'm not against the bottom-up approach outright. Tomas already notes in [3] that
an FK join needs no filter at all, since every outer tuple finds a match — and
that is a plan-time decision we can make exactly. So I would call it a starting
point for an incremental cost model rather than evidence that the general
problem is tractable.
Does anyone see a way to estimate unmatched rows that I have missed?
P.S. It seems to me that using CLOBBER_FREED_MEMORY you can catch assertion with
the v10-0001 patch.
[1] "I Can't Believe It's Not Yannakakis: Pragmatic Bitmap Filters in Microsoft
SQL Server", CIDR 2026 — https://www.vldb.org/cidrdb/papers/2026/p29-zhao.pdf
[2] "Including Bloom Filters in Bottom-up Optimization", arXiv:2505.02994 —
https://arxiv.org/abs/2505.02994
[3]
https://www.postgresql.org/message-id/a4700550-474f-42d8-b9fc-7e3dd0bfa818%40vondra.me
--
regards, Andrei Lepikhov,
pgEdge
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Jelte Fennema-Nio | 2026-09-02 18:14:21 | Re: Don't use the deprecated and insecure PQcancel in our frontend tools anymore |
| Previous Message | Melanie Plageman | 2026-09-02 18:06:24 | Re: Disallow outer-level and WHERE-clause aggregates in GRAPH_TABLE |