From 8069bf8e1c83bd671507543acfe8e7b117573f30 Mon Sep 17 00:00:00 2001 From: Tomas Vondra Date: Mon, 27 Jul 2026 15:50:30 +0200 Subject: [PATCH v9 17/21] Show expected filter selectivity in EXPLAIN The selectivity is included in EXPLAIN (VERBOSE) or EXPLAIN (ANALYZE) --- src/backend/commands/explain.c | 4 ++++ src/test/regress/expected/join.out | 22 +++++++++---------- src/test/regress/expected/returning.out | 6 ++--- src/test/regress/expected/select_parallel.out | 2 +- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index eb92d0e094b..f42a593397d 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -2676,6 +2676,10 @@ show_bloom_filter_info(PlanState *planstate, List *ancestors, appendStringInfo(&buf, "Bloom Filter %d: keys=%s", bf->producer_id, keys.data); + if (es->verbose || es->analyze) + appendStringInfo(&buf, " expected=%.1f%%", + bf->selectivity * 100.0); + /* include the counts only during ANALYZE */ if (es->analyze && bfs != NULL) { diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index c56df9ae0d1..23c8b7a3c4a 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -6928,7 +6928,7 @@ where exists (select 1 from t t4 Hash Cond: (t6.b = t4.b) -> Seq Scan on pg_temp.t t6 Output: t6.a, t6.b - Bloom Filter 2: keys=(t6.b) + Bloom Filter 2: keys=(t6.b) expected=0.5% -> Hash Output: t4.b, t5.b, t5.a Bloom Filter 2 @@ -6938,7 +6938,7 @@ where exists (select 1 from t t4 Hash Cond: (t5.b = t4.b) -> Seq Scan on pg_temp.t t5 Output: t5.a, t5.b - Bloom Filter 1: keys=(t5.b) + Bloom Filter 1: keys=(t5.b) expected=0.5% -> Hash Output: t4.b, t4.a Bloom Filter 1 @@ -9684,14 +9684,14 @@ select * from j1 inner join j2 on j1.id > j2.id; -- ensure non-unique rel is not chosen as inner explain (verbose, costs off) select * from j1 inner join j3 on j1.id = j3.id; - QUERY PLAN --------------------------------------- + QUERY PLAN +----------------------------------------------------- Hash Join Output: j1.id, j3.id Hash Cond: (j1.id = j3.id) -> Seq Scan on public.j1 Output: j1.id - Bloom Filter 1: keys=(j1.id) + Bloom Filter 1: keys=(j1.id) expected=66.7% -> Hash Output: j3.id Bloom Filter 1 @@ -9786,15 +9786,15 @@ select * from j1 natural join j2; explain (verbose, costs off) select * from j1 inner join (select distinct id from j3) j3 on j1.id = j3.id; - QUERY PLAN ------------------------------------------------ + QUERY PLAN +----------------------------------------------------- Hash Join Output: j1.id, j3.id Inner Unique: true Hash Cond: (j1.id = j3.id) -> Seq Scan on public.j1 Output: j1.id - Bloom Filter 1: keys=(j1.id) + Bloom Filter 1: keys=(j1.id) expected=33.3% -> Hash Output: j3.id Bloom Filter 1 @@ -9811,15 +9811,15 @@ inner join (select distinct id from j3) j3 on j1.id = j3.id; explain (verbose, costs off) select * from j1 inner join (select id from j3 group by id) j3 on j1.id = j3.id; - QUERY PLAN ------------------------------------------------ + QUERY PLAN +----------------------------------------------------- Hash Join Output: j1.id, j3.id Inner Unique: true Hash Cond: (j1.id = j3.id) -> Seq Scan on public.j1 Output: j1.id - Bloom Filter 1: keys=(j1.id) + Bloom Filter 1: keys=(j1.id) expected=33.3% -> Hash Output: j3.id Bloom Filter 1 diff --git a/src/test/regress/expected/returning.out b/src/test/regress/expected/returning.out index 50cd3be8030..7cfaa114137 100644 --- a/src/test/regress/expected/returning.out +++ b/src/test/regress/expected/returning.out @@ -716,7 +716,7 @@ UPDATE joinview SET f3 = f3 + 1 WHERE f3 = 57 Hash Cond: (joinme_1.f2j = foo_1.f2) -> Seq Scan on pg_temp.joinme joinme_1 Output: joinme_1.ctid, joinme_1.f2j - Bloom Filter 2: keys=(joinme_1.f2j) + Bloom Filter 2: keys=(joinme_1.f2j) expected=2.0% -> Hash Output: foo_1.f2, foo_1.tableoid, foo_1.ctid, joinme.ctid, joinme.other, joinme.f2j, foo_2.f1, foo_2.f3, foo_2.ctid, foo_2.f2, foo_2.tableoid Bloom Filter 2 @@ -725,7 +725,7 @@ UPDATE joinview SET f3 = f3 + 1 WHERE f3 = 57 Hash Cond: (joinme.f2j = foo_1.f2) -> Seq Scan on pg_temp.joinme Output: joinme.ctid, joinme.other, joinme.f2j - Bloom Filter 1: keys=(joinme.f2j) + Bloom Filter 1: keys=(joinme.f2j) expected=2.0% -> Hash Output: foo_1.f2, foo_1.tableoid, foo_1.ctid, foo_2.f1, foo_2.f3, foo_2.ctid, foo_2.f2, foo_2.tableoid Bloom Filter 1 @@ -795,7 +795,7 @@ UPDATE joinview SET f3 = f3 + 1, f4 = 7 WHERE f3 = 58 Hash Cond: (joinme.f2j = foo.f2) -> Seq Scan on pg_temp.joinme Output: joinme.other, joinme.ctid, joinme.f2j - Bloom Filter 1: keys=(joinme.f2j) + Bloom Filter 1: keys=(joinme.f2j) expected=0.5% -> Hash Output: foo.f3, foo.f1, foo.f2, foo.f4, foo.ctid, foo.tableoid Bloom Filter 1 diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out index 8f800a66c5e..9d6d213d3e1 100644 --- a/src/test/regress/expected/select_parallel.out +++ b/src/test/regress/expected/select_parallel.out @@ -1133,7 +1133,7 @@ explain (costs off, verbose) Hash Cond: ((a.unique1 = b.unique1) AND (a.two = (row_number() OVER w1))) -> Seq Scan on public.tenk1 a Output: a.unique1, a.unique2, a.two, a.four, a.ten, a.twenty, a.hundred, a.thousand, a.twothousand, a.fivethous, a.tenthous, a.odd, a.even, a.stringu1, a.stringu2, a.string4 - Bloom Filter 1: keys=(a.unique1, a.two) + Bloom Filter 1: keys=(a.unique1, a.two) expected=0.5% -> Hash Output: b.unique1, (row_number() OVER w1) Bloom Filter 1 -- 2.50.1 (Apple Git-155)