PostgreSQL-还原的数据库小于原始数据库

PostgreSQL-还原的数据库小于原始数据库,postgresql,Postgresql,我已经使用pg_dump to“.sql”文件备份了我的PostgreSQL数据库。 当我恢复数据库时,它的大小是2.8GB,而源(原始)数据库的大小是3.7GB。访问数据库的应用程序似乎工作正常 还原数据库的大小变小的原因是什么?原因很简单:在正常操作期间,当行被更新时,PostgreSQL会添加行的新副本,并将行的旧副本标记为已删除。这是正在运行的多版本并发控制(MVCC)。然后真空回收旧行所占用的空间,用于将来可插入的数据,但不将该空间返回到操作系统,因为它在文件的中间。请注意,VACUU

我已经使用pg_dump to“.sql”文件备份了我的PostgreSQL数据库。 当我恢复数据库时,它的大小是2.8GB,而源(原始)数据库的大小是3.7GB。访问数据库的应用程序似乎工作正常


还原数据库的大小变小的原因是什么?

原因很简单:在正常操作期间,当行被更新时,PostgreSQL会添加行的新副本,并将行的旧副本标记为已删除。这是正在运行的多版本并发控制(MVCC)。然后<代码>真空回收旧行所占用的空间,用于将来可插入的数据,但不将该空间返回到操作系统,因为它在文件的中间。请注意,
VACUUM
只有在表中修改了足够的数据或从表中删除了足够的数据后才会立即执行


你所看到的是完全正常的。它只是表明PostgreSQL数据库的大小将大于行大小之和。当您开始积极使用新数据库时,它很可能最终会增长到3.7GB。

简单的回答是,数据库存储在速度方面比空间方面更优化

例如,如果在一个表中插入100行,然后删除每个ID为奇数的行,DBMS可以写出一个只有50行的新表,但更有效的方法是将删除的行标记为可用空间,并在下次插入行时重用它们。因此,该表占用的空间是当前所需空间的两倍

Postgres在事务管理中使用“MVCC”,而不是锁定,这使得这种情况更加可能发生,因为更新通常涉及将新行写入存储,然后在没有事务查看旧行时将其标记为已删除

通过转储和恢复数据库,可以在没有所有可用空间的情况下重新创建数据库。这就是
VACUUM FULL
命令的基本功能-它将当前数据重写为新文件,然后删除旧文件

有一个可以让你检查其中一些的。e、 g.您可以列出主表大小(不包括单独“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;