Add test for HeapBitmapScan's broken skip_fetch optimization
In the previous commit HeapBitmapScan's skip_fetch optimization was removed, due to being broken in not easily fixable ways. Add a test that verifies we don't re-introduce this bug if somebody tries to re-add the feature. Only add the test to master for now, it's possible it's not entirely stable. That seems sufficient, as we're not going to re-introduce the feature on the backbranches. I did verify that the test passes on all branches. If the test turns out to be unproblematic, we can backpatch it later, should we feel a need to do so. Discussion: https://postgr.es/m/CAEze2Wg3gXXZTr6_rwC+s4-o2ZVFB5F985uUSgJTsECx6AmGcQ@mail.gmail.com
This commit is contained in:
parent
459e7bf8e2
commit
24da5b239a
48
src/test/isolation/expected/index-only-bitmapscan.out
Normal file
48
src/test/isolation/expected/index-only-bitmapscan.out
Normal file
@ -0,0 +1,48 @@
|
||||
Parsed test spec with 2 sessions
|
||||
|
||||
starting permutation: s2_vacuum s2_mod s1_explain s1_begin s1_prepare s1_fetch_1 s2_vacuum s1_fetch_all s1_commit
|
||||
step s2_vacuum:
|
||||
VACUUM (TRUNCATE false) ios_bitmap;
|
||||
|
||||
step s2_mod:
|
||||
DELETE FROM ios_bitmap WHERE a > 1;
|
||||
|
||||
step s1_explain:
|
||||
EXPlAIN (COSTS OFF) DECLARE foo NO SCROLL CURSOR FOR SELECT row_number() OVER () FROM ios_bitmap WHERE a > 0 or b > 0;
|
||||
|
||||
QUERY PLAN
|
||||
---------------------------------------------------
|
||||
WindowAgg
|
||||
Window: w1 AS (ROWS UNBOUNDED PRECEDING)
|
||||
-> Bitmap Heap Scan on ios_bitmap
|
||||
Recheck Cond: ((a > 0) OR (b > 0))
|
||||
-> BitmapOr
|
||||
-> Bitmap Index Scan on ios_bitmap_a
|
||||
Index Cond: (a > 0)
|
||||
-> Bitmap Index Scan on ios_bitmap_b
|
||||
Index Cond: (b > 0)
|
||||
(9 rows)
|
||||
|
||||
step s1_begin: BEGIN;
|
||||
step s1_prepare:
|
||||
DECLARE foo NO SCROLL CURSOR FOR SELECT row_number() OVER () FROM ios_bitmap WHERE a > 0 or b > 0;
|
||||
|
||||
step s1_fetch_1:
|
||||
FETCH FROM foo;
|
||||
|
||||
row_number
|
||||
----------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
step s2_vacuum:
|
||||
VACUUM (TRUNCATE false) ios_bitmap;
|
||||
|
||||
step s1_fetch_all:
|
||||
FETCH ALL FROM foo;
|
||||
|
||||
row_number
|
||||
----------
|
||||
(0 rows)
|
||||
|
||||
step s1_commit: COMMIT;
|
@ -17,6 +17,7 @@ test: partial-index
|
||||
test: two-ids
|
||||
test: multiple-row-versions
|
||||
test: index-only-scan
|
||||
test: index-only-bitmapscan
|
||||
test: predicate-lock-hot-tuple
|
||||
test: update-conflict-out
|
||||
test: deadlock-simple
|
||||
|
108
src/test/isolation/specs/index-only-bitmapscan.spec
Normal file
108
src/test/isolation/specs/index-only-bitmapscan.spec
Normal file
@ -0,0 +1,108 @@
|
||||
# In the past we supported index-only bitmap heapscans. However the
|
||||
# implementation was unsound, see
|
||||
# https://postgr.es/m/873c33c5-ef9e-41f6-80b2-2f5e11869f1c%40garret.ru
|
||||
#
|
||||
# This test reliably triggered the problem before we removed the
|
||||
# optimization. We keep the test around to make it less likely for a similar
|
||||
# problem to be re-introduced.
|
||||
|
||||
setup
|
||||
{
|
||||
-- by using a low fillfactor and a wide tuple we can get multiple blocks
|
||||
-- with just few rows
|
||||
CREATE TABLE ios_bitmap (a int NOT NULL, b int not null, pad char(1024) default '')
|
||||
WITH (AUTOVACUUM_ENABLED = false, FILLFACTOR = 10);
|
||||
|
||||
INSERT INTO ios_bitmap SELECT g.i, g.i FROM generate_series(1, 10) g(i);
|
||||
|
||||
CREATE INDEX ios_bitmap_a ON ios_bitmap(a);
|
||||
CREATE INDEX ios_bitmap_b ON ios_bitmap(b);
|
||||
}
|
||||
|
||||
teardown
|
||||
{
|
||||
DROP TABLE ios_bitmap;
|
||||
}
|
||||
|
||||
|
||||
session s1
|
||||
|
||||
setup
|
||||
{
|
||||
SET enable_seqscan = false;
|
||||
}
|
||||
|
||||
step s1_begin { BEGIN; }
|
||||
step s1_commit { COMMIT; }
|
||||
|
||||
|
||||
# The test query uses an or between two indexes to ensure make it more likely
|
||||
# to use a bitmap index scan
|
||||
#
|
||||
# The row_number() hack is a way to have something returned (isolationtester
|
||||
# doesn't display empty rows) while still allowing for the index-only scan
|
||||
# optimization in bitmap heap scans, which requires an empty targetlist.
|
||||
step s1_prepare
|
||||
{
|
||||
DECLARE foo NO SCROLL CURSOR FOR SELECT row_number() OVER () FROM ios_bitmap WHERE a > 0 or b > 0;
|
||||
}
|
||||
|
||||
step s1_explain
|
||||
{
|
||||
EXPlAIN (COSTS OFF) DECLARE foo NO SCROLL CURSOR FOR SELECT row_number() OVER () FROM ios_bitmap WHERE a > 0 or b > 0;
|
||||
}
|
||||
|
||||
step s1_fetch_1
|
||||
{
|
||||
FETCH FROM foo;
|
||||
}
|
||||
|
||||
step s1_fetch_all
|
||||
{
|
||||
FETCH ALL FROM foo;
|
||||
}
|
||||
|
||||
|
||||
session s2
|
||||
|
||||
# Don't delete row 1 so we have a row for the cursor to "rest" on.
|
||||
step s2_mod
|
||||
{
|
||||
DELETE FROM ios_bitmap WHERE a > 1;
|
||||
}
|
||||
|
||||
# Disable truncation, as otherwise we'll just wait for a timeout while trying
|
||||
# to acquire the lock
|
||||
step s2_vacuum
|
||||
{
|
||||
VACUUM (TRUNCATE false) ios_bitmap;
|
||||
}
|
||||
|
||||
permutation
|
||||
# Vacuum first, to ensure VM exists, otherwise the bitmapscan will consider
|
||||
# VM to be size 0, due to caching. Can't do that in setup because
|
||||
s2_vacuum
|
||||
|
||||
# Delete nearly all rows, to make issue visible
|
||||
s2_mod
|
||||
|
||||
# Verify that the appropriate plan is chosen
|
||||
s1_explain
|
||||
|
||||
# Create a cursor
|
||||
s1_begin
|
||||
s1_prepare
|
||||
|
||||
# Fetch one row from the cursor, that ensures the index scan portion is done
|
||||
# before the vacuum in the next step
|
||||
s1_fetch_1
|
||||
|
||||
# With the bug this vacuum would have marked pages as all-visible that the
|
||||
# scan in the next step then would have considered all-visible, despite all
|
||||
# rows from those pages having been removed.
|
||||
s2_vacuum
|
||||
|
||||
# If this returns any rows, the bug is present
|
||||
s1_fetch_all
|
||||
|
||||
s1_commit
|
Loading…
x
Reference in New Issue
Block a user