Het korte antwoord is dat databaseopslag meer is geoptimaliseerd voor snelheid dan voor ruimte.
Als u bijvoorbeeld 100 rijen in een tabel hebt ingevoegd en vervolgens elke rij met een oneven genummerde ID hebt verwijderd, kan de DBMS een nieuwe tabel met slechts 50 rijen wegschrijven, maar het is efficiënter om de verwijderde rijen eenvoudigweg als vrije ruimte te markeren en hergebruik ze wanneer u de volgende keer een rij invoegt. Daarom neemt de tafel twee keer zoveel ruimte in beslag als momenteel nodig is.
Postgres' gebruik van "MVCC", in plaats van te vergrendelen, voor transactiebeheer maakt dit nog waarschijnlijker, aangezien een UPDATE meestal inhoudt dat een nieuwe rij naar de opslag wordt geschreven en vervolgens de oude rij wordt verwijderd als er geen transacties naar kijken.
Door de database te dumpen en te herstellen, maakt u een DB opnieuw aan zonder al deze vrije ruimte. Dit is in wezen wat de VACUUM FULL
commando doet - het herschrijft de huidige gegevens in een nieuw bestand en verwijdert vervolgens het oude bestand.
Er is een extensie gedistribueerd met Postgres genaamd pg_freespace
waarmee je een deel hiervan kunt onderzoeken. bijv. u kunt de hoofdtabelgrootte (exclusief indexen en kolommen opgeslagen in afzonderlijke "TOAST" -tabellen) en de vrije ruimte die door elke tabel wordt gebruikt, weergeven met het onderstaande:
Select oid::regclass::varchar as table,
pg_size_pretty(pg_relation_size(oid)/1024 * 1024) As size,
pg_size_pretty(sum(free)) As free
From (
Select c.oid,
(pg_freespace(c.oid)).avail As free
From pg_class c
Join pg_namespace n on n.oid = c.relnamespace
Where c.relkind = 'r'
And n.nspname Not In ('information_schema', 'pg_catalog')
) tbl
Group By oid
Order By pg_relation_size(oid) Desc, sum(free) Desc;