Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a3e6c6f

Browse files
BitmapHeapScan: Remove incorrect assert and reset field
04e72ed pushed the skip fetch optimization (allowing bitmap heap scans to operate like index-only scans if none of the underlying data is needed) into heap AM implementations of bitmap table scan callbacks. 04e72ed added an assert that all tuples in blocks eligible for the optimization had been NULL-filled and emitted by the end of the scan. This assert is incorrect when not all tuples need be scanned to execute the query; for example: a join in which not all inner tuples need to be scanned before skipping to the next outer tuple. Remove the assert and reset the field on which it previously asserted to avoid incorrectly emitting NULL-filled tuples from a previous scan on rescan. Author: Melanie Plageman Reviewed-by: Tomas Vondra, Michael Paquier, Alvaro Herrera Reported-by: Melanie Plageman Reproduced-by: Tomas Vondra, Richard Guo Discussion: https://postgr.es/m/CAMbWs48orzZVXa7-vP9Nt7vQWLTE04Qy4PePaLQYsVNQgo6qRg%40mail.gmail.com
1 parent fb5718f commit a3e6c6f

File tree

3 files changed

+66
-3
lines changed

3 files changed

+66
-3
lines changed

src/backend/access/heap/heapam.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,7 +1184,12 @@ heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
11841184
scan->rs_vmbuffer = InvalidBuffer;
11851185
}
11861186

1187-
Assert(scan->rs_empty_tuples_pending == 0);
1187+
/*
1188+
* Reset rs_empty_tuples_pending, a field only used by bitmap heap scan,
1189+
* to avoid incorrectly emitting NULL-filled tuples from a previous scan
1190+
* on rescan.
1191+
*/
1192+
scan->rs_empty_tuples_pending = 0;
11881193

11891194
/*
11901195
* The read stream is reset on rescan. This must be done before
@@ -1216,8 +1221,6 @@ heap_endscan(TableScanDesc sscan)
12161221
if (BufferIsValid(scan->rs_vmbuffer))
12171222
ReleaseBuffer(scan->rs_vmbuffer);
12181223

1219-
Assert(scan->rs_empty_tuples_pending == 0);
1220-
12211224
/*
12221225
* Must free the read stream before freeing the BufferAccessStrategy.
12231226
*/

src/test/regress/expected/join.out

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7924,3 +7924,39 @@ where exists (select 1 from j3
79247924
(13 rows)
79257925

79267926
drop table j3;
7927+
-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
7928+
-- tuples are discarded. This may occur when:
7929+
-- 1. A join doesn't require all inner tuples to be scanned for each outer
7930+
-- tuple, and
7931+
-- 2. The inner side is scanned using a bitmap heap scan, and
7932+
-- 3. The bitmap heap scan is eligible for the "skip fetch" optimization.
7933+
-- This optimization is usable when no data from the underlying table is
7934+
-- needed. Use a temp table so it is only visible to this backend and
7935+
-- vacuum may reliably mark all blocks in the table all visible in the
7936+
-- visibility map.
7937+
CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
7938+
INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
7939+
CREATE INDEX ON skip_fetch(a);
7940+
VACUUM (ANALYZE) skip_fetch;
7941+
SET enable_indexonlyscan = off;
7942+
SET enable_seqscan = off;
7943+
EXPLAIN (COSTS OFF)
7944+
SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
7945+
QUERY PLAN
7946+
---------------------------------------------------------
7947+
Nested Loop Anti Join
7948+
-> Seq Scan on skip_fetch t1
7949+
-> Materialize
7950+
-> Bitmap Heap Scan on skip_fetch t2
7951+
Recheck Cond: (a = 1)
7952+
-> Bitmap Index Scan on skip_fetch_a_idx
7953+
Index Cond: (a = 1)
7954+
(7 rows)
7955+
7956+
SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
7957+
a
7958+
---
7959+
(0 rows)
7960+
7961+
RESET enable_indexonlyscan;
7962+
RESET enable_seqscan;

src/test/regress/sql/join.sql

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2904,3 +2904,27 @@ where exists (select 1 from j3
29042904
and t1.unique1 < 1;
29052905

29062906
drop table j3;
2907+
2908+
-- Exercise the "skip fetch" Bitmap Heap Scan optimization when candidate
2909+
-- tuples are discarded. This may occur when:
2910+
-- 1. A join doesn't require all inner tuples to be scanned for each outer
2911+
-- tuple, and
2912+
-- 2. The inner side is scanned using a bitmap heap scan, and
2913+
-- 3. The bitmap heap scan is eligible for the "skip fetch" optimization.
2914+
-- This optimization is usable when no data from the underlying table is
2915+
-- needed. Use a temp table so it is only visible to this backend and
2916+
-- vacuum may reliably mark all blocks in the table all visible in the
2917+
-- visibility map.
2918+
CREATE TEMP TABLE skip_fetch (a INT, b INT) WITH (fillfactor=10);
2919+
INSERT INTO skip_fetch SELECT i % 3, i FROM generate_series(0,30) i;
2920+
CREATE INDEX ON skip_fetch(a);
2921+
VACUUM (ANALYZE) skip_fetch;
2922+
2923+
SET enable_indexonlyscan = off;
2924+
SET enable_seqscan = off;
2925+
EXPLAIN (COSTS OFF)
2926+
SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
2927+
SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS NULL;
2928+
2929+
RESET enable_indexonlyscan;
2930+
RESET enable_seqscan;

0 commit comments

Comments
 (0)