在大型数据集上删除 Postgres 中的列

问题描述 投票:0回答:2

所以我有一个包含大型数据集的表,并且该表有我想删除的三列。
问题是:Postgres 将如何处理?

它会遍历每个条目还是只会更新映射信息而不需要太多开销? 我可以制作一个

ALTER TABLE
还是在这种特殊情况下我应该使用交换表?

而且,如果有什么区别的话,所有三列都有固定长度(两个整数和一个数字)。

如果已经被问过,我很抱歉,但谷歌找不到任何相关的问题/文章......

postgresql database-design ddl database-performance postgresql-9.2
2个回答
79
投票

ALTER TABLE DROP COLUMN 仅禁用系统表中的列。它非常快,但它不会从堆文件中删除数据。您必须稍后执行 VACUUM FULL 来压缩分配的文件空间。所以 ALTER TABLE DROP COLUMN 非常快。为了压缩文件,你必须调用速度较慢的(带有独占锁定)VACUUM FULL。


72
投票

谷歌可能对这个问题毫无用处,但是手册很少失败

DROP COLUMN
形式不会物理移除色谱柱,但 只是使其对 SQL 操作不可见。随后插入和 表中的更新操作将为该列存储空值。 因此,删除一列很快,但不会立即减少 表的磁盘大小,即删除的表占用的空间 列不被回收。随着时间的推移,该空间将被回收 现有行已更新。

并且:

要强制立即重写表格,您可以使用

VACUUM FULL
CLUSTER
或强制重写的
ALTER TABLE
形式之一。 这会导致表中没有语义可见的更改,但得到 摆脱不再有用的数据。

具体来说,系统目录表

attisdropped
中的列
pg_attribute
设置为
true

副作用

有轻微的副作用(正如Chris指出的):

  • 更新或新插入的行仍然存储不可见的空值,这会强制每个新行使用空位图,即使可见列中没有空值也是如此。 不会影响现有行,因为这些行保留原始(现在不可见)列值。

  • 空位图必须足够大以覆盖所有可见的删除的列。在极端情况下,它可能会因此被放大。关于有效尺寸:

  • 删除的列计入允许的最大值(无论如何您都不应该刮擦)。

  • 目前(Postgres 16)没有简单的方法可以完全摆脱 zombi 列。上面提到的表重写用

    null
    替换不可见的值,这会回收 几乎所有空间,但不会从系统目录中清除删除的列。甚至
    TRUNCATE
    也没有。只有创建新表或转储/恢复周期才能做到这一点。

© www.soinside.com 2019 - 2024. All rights reserved.