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

Posted

技术标签:

【中文标题】在大型数据集上删除 Postgres 中的列【英文标题】:Dropping column in Postgres on a large dataset 【发布时间】:2013-03-19 23:05:52 【问题描述】:

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

它会遍历每个条目还是只更新映射信息而没有太多开销? 我可以只创建一个ALTER TABLE 还是在这种特殊情况下使用交换表?

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

很抱歉,如果已经有人问过了,但 Google 找不到任何相关的问题/文章...

【问题讨论】:

【参考方案1】:

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

【讨论】:

【参考方案2】:

这个问题谷歌可能没用,但是the manual rarely fails:

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

还有:

要强制立即重写表,您可以使用VACUUM FULLCLUSTER 或强制重写的ALTER TABLE 的一种形式。 这导致表中没有语义上可见的变化,但得到 删除不再有用的数据。

具体来说,系统目录表pg_attribute中的attisdropped列设置为true

副作用

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

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

NULL 位图必须足够大以覆盖所有可见的 已删除的列。在极端情况下,这可能会扩大 NULL 位图。关于有效尺寸:

Do nullable columns occupy additional space in PostgreSQL?

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

目前(Postgres 13)没有简单的方法可以完全摆脱僵尸列。上面提到的表重写将不可见的值替换为 NULL(这会回收几乎所有空间),但都不会从系统目录中清除已删除的列。甚至没有TRUNCATE。只有创建一个新表(或转储/恢复周期)才能做到这一点。

【讨论】:

有趣的是,因为行更新现在将在删除的列中“存储”NULL。而且因为 postgresql 通过在可选的“空位图”中设置一个位来存储空值,所以 每一 行现在必须有一个空位图(每八个删除或未删除的列的大小为一个字节)甚至如果没有可见行为 NULL

以上是关于在大型数据集上删除 Postgres 中的列的主要内容,如果未能解决你的问题,请参考以下文章

Weka 中的 KNN 算法永远不会在大型数据集上完成

大型数据集上的 R 中的 hclust()

如何在 python 中的大型数据集上训练随机森林?

大型数据集上的 R 中的矩阵数学

Spacy,在 python 中的大型数据集上使用 nlp.pipe,多处理导致进程进入睡眠状态。如何正确使用所有 CPU 内核?

大型数据集上的 MongoDB 子文档查询性能