> If you subtract recently dead from that number within the heap 
> implementation, then it will no longer
> reflect non-removable tuples and the log message in the cluster
> function "found %.0f removable, %.0f nonremovable row versions" will no 
> longer be correct.

Yes, that's correct. I did not pay attention to the logging aspect.

Here is a test with and without the patch. While there is a long-running
serializable transaction in another session, running an update followed
by a normal vacuum sets the reltuples value correctly to 10. A follow-up
VACUUM FULL then sets it incorrectly to 14. The patch, which sets
the num_tuples after the logging, ensures that the logging is correct
and that pg_class.reltuples matches the actual number of live tuples.


-- without the patch

test=# UPDATE stats SET a=1 WHERE a > 6;
UPDATE 4
test=# SELECT reltuples FROM pg_class WHERE relname = 'stats';
 reltuples
-----------
        -1
(1 row)

test=# vacuum verbose stats;
INFO:  vacuuming "test.public.stats"
INFO:  finished vacuuming "test.public.stats": index scans: 0
pages: 0 removed, 1 remain, 1 scanned (100.00% of total), 0 eagerly scanned
tuples: 0 removed, 14 remain, 4 are dead but not yet removable
removable cutoff: 789, which was 1 XIDs old when operation ended
new relfrozenxid: 788, which is 1 XIDs ahead of previous value
frozen: 0 pages from table (0.00% of total) had 0 tuples frozen
visibility map: 0 pages set all-visible, 0 pages set all-frozen (0
were all-visible)
index scan not needed: 0 pages from table (0.00% of total) had 0 dead
item identifiers removed
avg read rate: 0.000 MB/s, avg write rate: 9.159 MB/s
buffer usage: 14 hits, 0 reads, 3 dirtied
WAL usage: 4 records, 3 full page images, 24981 bytes, 0 buffers full
system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s
VACUUM
test=# SELECT reltuples FROM pg_class WHERE relname = 'stats';
 reltuples
-----------
        10
(1 row)

test=# VACUUM (verbose, FULL) stats;
INFO:  vacuuming "public.stats"
INFO:  "public.stats": found 0 removable, 14 nonremovable row versions
in 1 pages
DETAIL:  4 dead row versions cannot be removed yet.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
VACUUM
test=# SELECT reltuples FROM pg_class WHERE relname = 'stats';
 reltuples
-----------
        14
(1 row)



-- with the patch

test=# UPDATE stats SET a=1 WHERE a > 6;
UPDATE 4
test=#
test=# SELECT reltuples FROM pg_class WHERE relname = 'stats';
 reltuples
-----------
        -1
(1 row)

test=# VACUUM verbose stats;
INFO:  vacuuming "test.public.stats"
INFO:  finished vacuuming "test.public.stats": index scans: 0
pages: 0 removed, 1 remain, 1 scanned (100.00% of total), 0 eagerly scanned
tuples: 0 removed, 14 remain, 4 are dead but not yet removable
removable cutoff: 794, which was 1 XIDs old when operation ended
new relfrozenxid: 793, which is 1 XIDs ahead of previous value
frozen: 0 pages from table (0.00% of total) had 0 tuples frozen
visibility map: 0 pages set all-visible, 0 pages set all-frozen (0
were all-visible)
index scan not needed: 0 pages from table (0.00% of total) had 0 dead
item identifiers removed
avg read rate: 0.000 MB/s, avg write rate: 9.195 MB/s
buffer usage: 17 hits, 0 reads, 3 dirtied
WAL usage: 4 records, 3 full page images, 24981 bytes, 0 buffers full
system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s
VACUUM
test=# SELECT reltuples FROM pg_class WHERE relname = 'stats';
 reltuples
-----------
        10
(1 row)

test=# VACUUM (verbose, FULL) stats;
INFO:  vacuuming "public.stats"
INFO:  "public.stats": found 0 removable, 14 nonremovable row versions
in 1 pages
DETAIL:  4 dead row versions cannot be removed yet.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
VACUUM
test=# SELECT reltuples FROM pg_class WHERE relname = 'stats';
 reltuples
-----------
        10
(1 row)


--
Sami


Reply via email to