VACUUM
通常不会将磁盘空间归还给操作系统,除非在某些特殊情况下。
从文档:
VACUUM
删除表和索引中的死行版本并标记可用空间以供将来重用的标准形式。但是,它不会将空间返回给操作系统,除非在特殊情况下,表末尾的一个或多个页面变得完全空闲并且可以轻松获得排他表锁。相反,VACUUM FULL
通过编写没有死空间的完整新版本的表文件来主动压缩表。这可以最小化表的大小,但可能需要很长时间。它还需要额外的磁盘空间来存储表的新副本,直到操作完成。
问题是:如何实现这个数据库状态one or more pages at the end of a table become entirely free
?这可以通过 来完成VACUUM FULL
,但我没有足够的空间来实现它。那么还有其他可能吗?
要将空间返回给操作系统,请使用
VACUUM FULL
. 在这期间,我想你会跑VACUUM FULL ANALYZE
。我引用手册:大胆强调我的。
CLUSTER
作为附带效应,也实现了这一点。Plain
VACUUM
通常无法实现您的目标(“表格末尾的一个或多个页面完全免费”)。当机会出现时,它不会重新排序行,只会从文件的物理末尾修剪空页面 - 就像您从手册中引用的那样。当您在附加其他元组之前获得
INSERT
一批行和它们时,您可以在物理文件的末尾获得空页。DELETE
或者,如果删除了足够多的行,这可能是巧合。还有一些特殊设置可能会阻止
VACUUM FULL
回收空间。看:在表格末尾准备空白页以进行测试
系统列
ctid
代表一行的物理位置。您需要了解该列:我们可以使用它并通过从最后一页删除所有行来准备一个表:
现在,最后一页是空的。这忽略了并发写入。要么您是唯一一个写入该表的人,要么您需要获取写锁以防止出现竞争条件。
该查询经过优化,可以快速识别符合条件的行。a 的第二个数字
tid
是存储为 unsigned 的元组索引int2
,并且65535
是该类型 (2^16 - 1
) 的最大值,因此这是安全的上限。db<>fiddle here (重用不同情况下的简单表。)
旧的 sqlfiddle
测量行/表大小的工具:
磁盘已满
对于任何这些操作,您都需要在磁盘上留出回旋余地。还有社区工具
pg_repack
可以替代VACUUM FULL
/CLUSTER
。它避免了独占锁,但也需要可用空间来使用。手册:作为最后的手段,您可以运行转储/恢复周期。这也消除了表和索引中的所有膨胀。密切相关的问题:
那边的答案相当激进。如果您的情况允许(没有外键或其他引用阻止行删除),并且没有对表的并发访问),您可以:
将表转储到从具有大量磁盘空间的远程计算机连接的磁盘(for ):
-a
--data-only
从远程 shell,转储表数据:
在 pg 会话中,
TRUNCATE
该表:从远程 shell,恢复到同一个表:
它现在没有任何死行或膨胀。
但也许你可以更简单?
您可以通过删除(移动)不相关的文件在磁盘上腾出足够的空间吗?
您可以
VACUUM FULL
先一张一张地缩小表,从而释放足够的磁盘空间吗?您可以运行
REINDEX TABLE
或REINDEX INDEX
从臃肿的索引中释放磁盘空间吗?无论做什么,都不要轻举妄动。如有疑问,请先将所有内容备份到安全位置。