我正在使用 PostgreSQL,并且在向现有表添加新列时担心表膨胀。据我所知,PostgreSQL 使用多版本并发控制 (MVCC) 和 autovacuum 来回收旧行的空间。
这是场景:
假设我有一个以example_table
现有数据命名的表,并且我决定添加一个新列,例如new_column
更大数据类型的列:
ALTER TABLE example_table ADD COLUMN new_column VARCHAR(255);
此外,我将使用新值更新新列:
UPDATE example_table SET new_column = 'some_value';
据我了解,执行此操作后,旧行将被标记为死亡,并且 autovacuum 最终将回收空间。但是,与添加列的新行相比,旧行的大小较小。
我有以下问题:
- 考虑到新旧行之间的大小差异,PostgreSQL(特别是 Autovacuum)如何处理从旧行回收的空间?
- 由于大小差异,死元组无法重用,此过程是否可能导致表膨胀?
- 在这种情况下是否有必要执行 VACUUM FULL 来有效回收空间,或者 autovacuum 是否可以充分处理它?
如果新值是常量文字,您可以添加已填充的列,而无需创建任何死元组:
如果您必须将其作为更新来执行,那么生成的可用空间最终将是可重用的。VACUUM 将对多个旧元组(同一页面中)的可用空间进行碎片整理,以便可用于更大的新元组。当然,假设任何一页上都有足够的旧元组来添加到该可用空间量。这样做确实需要页面上的“超级独占”锁,但这不太可能成为长期的大规模问题。