Краткият отговор е, че съхранението на база данни е по-оптимизирано за скорост, отколкото за пространство.
Например, ако вмъкнете 100 реда в таблица, след което изтриете всеки ред с нечетно номериран идентификатор, СУБД може да напише нова таблица само с 50 реда, но за нея е по-ефективно просто да маркира изтритите редове като свободно пространство и ги използвайте повторно, когато следващия път вмъкнете ред. Следователно таблицата заема два пъти повече място, отколкото е необходимо в момента.
Използването на "MVCC" от Postgres вместо заключване за управление на транзакции прави това още по-вероятно, тъй като АКТУАЛИЗАЦИЯТА обикновено включва запис на нов ред в хранилището, след което старият ред се маркира като изтрит, след като нито една транзакция не го гледа.
Като изхвърляте и възстановявате базата данни, вие създавате отново DB без цялото това свободно пространство. По същество това е VACUUM FULL
команда прави - пренаписва текущите данни в нов файл, след което изтрива стария файл.
Има разширение, разпространявано с Postgres, наречено pg_freespace
което ви позволява да разгледате част от това. напр. можете да изброите размера на основната таблица (без индексите и колоните, съхранявани в отделни таблици „TOAST“) и свободното пространство, използвано от всяка таблица, с по-долу:
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;