PostgreSQL 9.0如何在删除后回收磁盘空间而不重建表?

我们的PostgreSQL 9.0 Windows生产服务器空间不足.

在我们的100GB数据库中,我们有一个包含TOASTed二进制数据的大表.我们删除了一些行,需要将空间返回给操作系统.

我们没有足够的空间来完全重写表,而我对CLUSTER,VACUUM FULL和pg_repack的所有读取都是他们需要重写表.到目前为止,我的google-fu还没有找到其他任何东西.

一些停机时间是可以接受的(约2小时),但是备份/恢复对于我们的目的来说太慢了,我也不热衷于在两个步骤之间放弃数据库.

问题:如何在不进行完整表重写的情况下将磁盘空间返回到操作系统?

(这是一个生产服务器,因此任何解决方案都必须具有信誉/推荐/支持等).

(P.S.可以使用一个单独的更大的磁盘,如果表可以在某种程度上重建它.表空间?)

最佳答案
如果您使用CLUSTER / VACUUM FULL / pg_repack(它们都自动管理锁定)以外的任何东西,您需要确保没有对表的并发写入.对表进行独占锁定并在单个事务中执行所有操作,或者更好的是,关闭所有连接以避免并发更改.

TABLESPACE

是的,你的最后一个想法可行.在另一个磁盘上创建一个新的表空间.

CREATE TABLESPACE ts1 LOCATION '/data/disk2';

然后在新表空间中创建表的优化副本:

CREATE TABLE new_tbl 
TABLESPACE ts1 AS
SELECT * FROM tbl
ORDER BY ....  -- ORDER BY is optional 

副本将紧密打包,没有死行.

然后你可能只是删除旧表并重命名新表以继续使用新磁盘.

或者,如果由于某种原因必须将其保留在旧磁盘上,请删除旧表,重命名新表并将其移回默认表空间.现在这个步骤要快得多:

ALTER TABLE tbl SET TABLESPACE pg_default

Per documentation:

This form changes the table’s tablespace to the specified tablespace
and moves the data file(s) associated with the table to the new
tablespace. Indexes on the table, if any, are not moved; but they can
be moved separately with additional SET TABLESPACE commands. See also
CREATE TABLESPACE.

无论哪种方式,都不要忘记(重新)创建所有依赖对象.索引,外键,视图,…

好吧,您可以使用ALTER TABLE tbl SET TABLESPACE …开始,但是表格不会按要求进行优化,只是按原样移动.但是你有足够的摆动空间然后运行pg_repack等.

复制

完整备份/恢复可能需要很长时间,但您只能对相关表执行此操作.

COPY tbl TO '/path/to/other/disk/tbl.pgsql';
TRUNCATE tbl;
COPY tbl FROM '/path/to/other/disk/tbl.pgsql';

桌子现在紧紧包裹着.

临时表

如果你碰巧有足够的RAM,你可以用RAM中的临时表做类似的事情.会快得多.详细说明:

> Best way to delete millions of rows by ID
> How to delete duplicate entries?

转载注明原文:PostgreSQL 9.0如何在删除后回收磁盘空间而不重建表? - 代码日志