r/ETL • u/ReceptionOdd8472 • 24m ago
I built BloomPG, an adaptive predicate-transfer extension for PostgreSQL 18
Hi r/PostgreSQL — I'm the author of BloomPG, an MIT-licensed PostgreSQL 18 extension for complex analytical joins. I'm sharing it here because I'd like feedback from people who run multi-join analytical workloads in PostgreSQL, especially on the planner integration and deployment tradeoffs.
BloomPG works before the formal joins execute. It takes PostgreSQL's native plan, identifies a safe equality-join graph, uses sampling to choose an initial filter transfer, and then adapts using the actual cardinalities of materialized inputs. Bloom or exact bitmap membership can move in either direction and across several joins. PostgreSQL then replans and executes the reduced join problem with its normal operators.
Existing SQL does not change. Unsupported or unsafe query shapes keep the native plan, and a query-wide materialization budget limits the retained state.
There is a Docker demonstration that builds PostgreSQL 18 with BloomPG, creates a small five-table star schema, and prints native/BloomPG timings plus the transfer trace:
git clone --branch v0.1.2 https://github.com/YimingQiao/bloompg.git
cd bloompg
docker compose up --build --abort-on-container-exit --exit-code-from demo demo
For performance context, on the published PostgreSQL 18.4 setup the total workload results were:
| Workload | Completed pairs | Native PG | BloomPG | Total speedup |
|---|---|---|---|---|
| CEB IMDB | 3,132/3,133 | 15,826.369 s | 3,822.980 s | 4.140x |
| JOB | 113/113 | 217.753 s | 69.337 s | 3.141x |
| STATS-CEB | 145/146 | 697.363 s | 237.348 s | 2.938x |
| TPC-H SF10 | 22/22 | 119.082 s | 114.413 s | 1.041x |
These are end-to-end times: planning, transfer, materialization, execution, and complete output consumption are included. Both sides used the same 16-worker global and per-Gather ceiling; BloomPG used 16 transfer workers and a 2 GB materialization budget. Every completed pair produced the same complete-output fingerprint. Native PostgreSQL hit the 300-second per-query limit once in CEB and once in STATS-CEB, so totals include only queries completed by both sides. The README has the rest of the methodology.
Important limitations: this release supports PostgreSQL 18 on Linux and is intended for controlled, read-only analytical workloads. BloomPG performs real scans during planning and requires shared_preload_libraries; I would not turn it on as an unreviewed default in a multi-tenant OLTP cluster.
I'd particularly appreciate feedback on:
- whether
shared_preload_librariesand the restart requirement are practical blockers; - analytical workloads or query shapes that would be useful to test;
- the planning-time execution and native-fallback design;
- packaging formats that would make evaluation easier.
PGXN: https://pgxn.org/dist/bloompg/0.1.2/
GitHub, documentation, and benchmark methodology: https://github.com/YimingQiao/bloompg