Question

I recently ended up deleting most of the data in one of our tables, on purpose. Normally the table is append-mostly, with a short window during which updates might happen after the original insert. However, most of the data recently got orphaned, and we decided to delete it.

our_db=> delete from my_schema.table where a_column not in (select distinct value from my_schema.another_table);
DELETE 6418263

I expected VACUUM to take care of the now-mostly-empty pages, but it failed to do so!

our_db=> vacuum(analyze, verbose, disable_page_skipping) my_schema.table;
INFO:  vacuuming "my_schema.table"
INFO:  index "table_pkey" now contains 2 row versions in 46486 pages
DETAIL:  0 index row versions were removed.
46481 index pages have been deleted, 46481 are currently reusable.
CPU: user: 0.21 s, system: 0.00 s, elapsed: 2.76 s.
INFO:  index "table_idx1" now contains 2 row versions in 98919 pages
DETAIL:  0 index row versions were removed.
98914 index pages have been deleted, 98914 are currently reusable.
CPU: user: 0.47 s, system: 0.00 s, elapsed: 5.50 s.
INFO:  index "table_idx2" now contains 2 row versions in 22324 pages
DETAIL:  0 index row versions were removed.
22317 index pages have been deleted, 22317 are currently reusable.
CPU: user: 0.10 s, system: 0.00 s, elapsed: 1.63 s.
INFO:  index "table_idx3" now contains 2 row versions in 22252 pages
DETAIL:  0 index row versions were removed.
22245 index pages have been deleted, 22245 are currently reusable.
CPU: user: 0.11 s, system: 0.00 s, elapsed: 1.68 s.
INFO:  index "table_idx4" now contains 2 row versions in 22373 pages
DETAIL:  0 index row versions were removed.
22366 index pages have been deleted, 22366 are currently reusable.
CPU: user: 0.09 s, system: 0.01 s, elapsed: 1.39 s.
INFO:  index "table_idx5" now contains 2 row versions in 69761 pages
DETAIL:  0 index row versions were removed.
69755 index pages have been deleted, 69755 are currently reusable.
CPU: user: 0.32 s, system: 0.00 s, elapsed: 4.98 s.
INFO:  index "table_idx6" now contains 2 row versions in 71399 pages
DETAIL:  0 index row versions were removed.
71388 index pages have been deleted, 71388 are currently reusable.
CPU: user: 0.31 s, system: 0.02 s, elapsed: 5.55 s.
INFO:  "table": found 0 removable, 2 nonremovable row versions in 754123 out of 754123 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 6840941
There were 6439255 unused item pointers.
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 4.55 s, system: 0.20 s, elapsed: 53.89 s.
INFO:  vacuuming "pg_toast.pg_toast_16458"
INFO:  index "pg_toast_16458_index" now contains 0 row versions in 1 pages
DETAIL:  0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO:  "pg_toast_16458": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 6840969
There were 0 unused item pointers.
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO:  analyzing "my_schema.table"
INFO:  "table": scanned 30000 of 754123 pages, containing 0 live rows and 0 dead rows; 0 rows in sample, 0 estimated total rows
VACUUM

Only two rows are alive, yet over 750000 pages are still occupied, and scanned if sequential scan is needed:

our_db=> SELECT count(id) FROM my_schema.table;
 count 
-------
     2
(1 row)

our_db=> explain analyze SELECT count(content) FROM my_schema.table;
                                                        QUERY PLAN                                                         
---------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=754123.00..754123.01 rows=1 width=8) (actual time=26795.676..26795.676 rows=1 loops=1)
   ->  Seq Scan on table  (cost=0.00..754123.00 rows=1 width=1036) (actual time=25683.699..26795.666 rows=2 loops=1)
 Planning time: 0.052 ms
 Execution time: 26795.703 ms
(4 rows)

Why doesn't VACUUM get rid of empty frozen pages, when disable_page_skipping is enabled?

Was it helpful?

Solution

This has nothing to do with freezing.

VACUUM doesn't shrink the table, except that it will truncate any empty pages at the end of the table. Obviously an autovacuum job was faster than your manual VACUUM, because there were no dead tuples left.

To shrink and reorganize the table, run

VACUUM (FULL) my_schema.table;

but be aware that this will exclusively lock the table for the duration of the operation.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top