La risposta breve è che l'archiviazione del database è più ottimizzata per la velocità che per lo spazio.
Ad esempio, se hai inserito 100 righe in una tabella, quindi hai eliminato ogni riga con un ID dispari, il DBMS potrebbe scrivere una nuova tabella con solo 50 righe, ma è più efficiente contrassegnare semplicemente le righe eliminate come spazio libero e riutilizzarli la prossima volta che inserirai una riga. Pertanto il tavolo occupa il doppio dello spazio necessario al momento.
L'uso di "MVCC" da parte di Postgres, anziché il blocco, per la gestione delle transazioni lo rende ancora più probabile, dal momento che un UPDATE di solito comporta la scrittura di una nuova riga nella memoria, quindi il contrassegno della vecchia riga eliminata una volta che nessuna transazione la sta esaminando.
Scaricando e ripristinando il database, stai ricreando un DB senza tutto questo spazio libero. Questo è essenzialmente ciò che il VACUUM FULL
comando fa - riscrive i dati correnti in un nuovo file, quindi elimina il vecchio file.
Esiste un'estensione estensione distribuita con Postgres chiamata pg_freespace
che ti consente di esaminare parte di questo. per esempio. puoi elencare le dimensioni della tabella principale (esclusi indici e colonne archiviate in tabelle "TOAST" separate) e lo spazio libero utilizzato da ciascuna tabella con quanto segue:
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;