我通过以下方式处理具有 ~10^7 行的表:获取最后 N 行,以某种方式更新它们,然后删除,然后是vacuum
表。最后,我查询pg_total_relation_size
. 循环重复,直到桌子结束。每次迭代持续几秒钟。除了上面提到的之外,该表没有任何其他查询。问题是我得到了相同的表大小结果。它大约每几个小时改变一次。
所以问题是——postgres 是在某个地方存储表大小还是每次调用函数时都会计算它?即,尽管经过处理,我的表格大小是否真的保持不变?
我通过以下方式处理具有 ~10^7 行的表:获取最后 N 行,以某种方式更新它们,然后删除,然后是vacuum
表。最后,我查询pg_total_relation_size
. 循环重复,直到桌子结束。每次迭代持续几秒钟。除了上面提到的之外,该表没有任何其他查询。问题是我得到了相同的表大小结果。它大约每几个小时改变一次。
所以问题是——postgres 是在某个地方存储表大小还是每次调用函数时都会计算它?即,尽管经过处理,我的表格大小是否真的保持不变?
尽管您正在执行DELETE
s 和ing,但您的表在磁盘上的大小确实保持不变。VACUUM
根据上的文档VACUUM
,普通VACUUM
只有在可以通过截断文件末尾的可用空间而不重新排列活动行的情况下才能将空间释放回操作系统。
该空间仍然是“空闲的”,因为 PostgreSQL 可以将其重新用于其他新行。重用 PostgreSQL 没有归还给操作系统的空间比扩展与新空间的关系要快得多,因此这通常是可取的。
Pg 不仅仅归还这个空间的另一个原因是,它只能在文件末尾之前没有可见行的连续块时将空间归还给操作系统。这不会发生太多,所以实际上 Pg 需要移动一些行以压缩表并允许它在最后释放空间,有点像文件系统上的碎片整理。这是一个低效且缓慢的过程,可能会违反直觉地使表的访问速度变慢而不是更快,因此这并不总是一个好主意。
如果您有一个大部分但并非完全为空的关系,则值得做一个VACUUM FULL
(Pg 9.0 及更高版本)或CLUSTER
(所有版本)来释放空间。如果您希望重新填满桌子,这通常会适得其反;实际上最好保持原样。
(对于我所说的“实时”和“可见”等术语的含义,请参阅MVCC 上的文档,这将帮助您了解 Pg 的表格组织。)
就您而言,我个人会跳过手册VACUUM
。如果需要,请打开 autovacuum。如果您真的需要,您可以考虑对表进行分区,TRUNCATE
逐个分区处理它,并在完成处理后对每个分区进行处理。