Concepts·PostgreSQL
PostgreSQL VACUUM and Table Bloat
An UPDATE of 133,333 rows leaves 133,333 dead tuples. VACUUM clears them and the table stays at exactly 47 MB. Only VACUUM FULL returns space - and it rewrites the whole table under an exclusive lock to do it.
Performance Guide 35 of 47 Advanced
- OSUbuntu 26.04 LTS
- PostgreSQL18.6-0ubuntu0.26.04.1
- Test data400,000 rows, 2 core / 4 GB host
- TimeAbout 17 min
This is a direct consequence of MVCC: an UPDATE writes a new row version and leaves the old one for concurrent readers. Every PostgreSQL table works this way, and autovacuum exists to manage it.
| Server Name | IP Address | OS | Roles | CPU | RAM | HDD |
|---|---|---|---|---|---|---|
| db-a01 | 192.168.0.81 | Ubuntu 26.04 LTS | Primary / Source / Replica Set Member 1 | 2 Core | 4 GB | 50 GB |
This guide includes
Use this when a table has grown and deleting or updating rows does not shrink it. This matters because VACUUM makes space reusable without returning it - only a rewrite gives the disk back.
- updating a third of the rows, and counting the dead tuples that leaves behind
- vacuuming, and watching the size not change at all
- rewriting the table with VACUUM FULL to actually get the space back
- reading the settings that make this automatic, which are already on
Before you start
- The
eventstable with 400,000 rows.
-
Update a third of the rows and count the dead ones
-
Vacuum, and watch the size not change
-
Rewrite the table to get the space back
-
Read the settings that make this automatic