Det korte svar er, at databaselagring er mere optimeret til hastighed end plads.
Hvis du f.eks. indsatte 100 rækker i en tabel og derefter slettede hver række med et ulige nummereret ID, kunne DBMS udskrive en ny tabel med kun 50 rækker, men det er mere effektivt for det blot at markere de slettede rækker som ledig plads og genbrug dem, næste gang du indsætter en række. Derfor fylder bordet dobbelt så meget, som der er behov for i øjeblikket.
Postgres' brug af "MVCC" i stedet for låsning til transaktionsstyring gør dette endnu mere sandsynligt, da en OPDATERING normalt involverer at skrive en ny række til lageret og derefter markere den gamle række som slettet, når ingen transaktioner ser på den.
Ved at dumpe og gendanne databasen genskaber du en DB uden al denne ledige plads. Dette er i bund og grund hvad VACUUM FULL
kommandoen gør - den omskriver de aktuelle data til en ny fil, og sletter derefter den gamle fil.
Der er en udvidelse distribueret med Postgres kaldet pg_freespace
som lader dig undersøge noget af dette. for eksempel. du kan angive hovedtabelstørrelsen (ikke inklusive indekser og kolonner gemt i separate "TOAST"-tabeller) og ledig plads, der bruges af hver tabel med nedenstående:
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;