【问题标题】:What is the effect on record size of reordering columns in PostgreSQL?对 PostgreSQL 中重新排序列的记录大小有什么影响?
【发布时间】:2010-04-08 16:09:32
【问题描述】:

由于 Postgres 只能在表的末尾添加列,我最终通过在表的末尾添加新列,将它们设置为与现有列相等,然后删除原始列来重新排序。

那么,PostgreSQL 对被删除的列释放的内存做了什么?它是否会自动重用内存,因此单个记录会消耗与以前相同的空间量?但这需要重写整个表,所以为避免这种情况,是否只是在每条记录中保留一堆空白?

【问题讨论】:

    标签: postgresql vacuum


    【解决方案1】:

    这个问题很老了,但由于两个答案都是错误的或具有误导性,我将添加另一个。

    更新一行时,Postgres 写入一个新的行版本,旧的行版本最终被VACUUM 删除,因为没有运行的事务可以看到它了。

    Plain VACUUM 不会将包含该表的物理文件的磁盘空间返回给系统,除非它在表的物理端发现完全死块或空块。您需要运行VACUUM FULLCLUSTER 来积极压缩表并将多余的空间返回给系统。这在正常操作中通常是不希望的。 Postgres 可以重复使用死元组来将新的行版本保留在同一数据页上,从而提高性能。

    在您的情况下,由于您更新每一行,因此表的大小加倍(从其最小大小开始)。建议运行 VACUUM FULL CLUSTER 将膨胀返回系统。
    两者都在表上使用排他锁。如果这会干扰并发访问,请考虑 pg_repack,它可以在没有排他锁的情况下执行相同的操作。

    澄清:运行CLUSTER 完全回收空间。 No VACUUM FULL is needed after CLUSTER (and vice versa).

    更多细节:

    【讨论】:

      【解决方案2】:

      来自docs

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

      您需要在CLUSTER 之后执行VACUUM FULL 来回收空间。

      【讨论】:

      • VACUUM FULL 只会在每一行都被更新时回收空间,它会在完全死行之后清理——而不是其他好行中的死列。由于设置新列的 UPDATE 必须在执行 DROP 之前发生,因此现在过时的列所占用的空间不会被它回收。只会清理该行的旧的原始副本。除了完全更新之外,您还可以执行 CLUSTER(在 PostgreSQL 8.3 或更高版本中)或创建表的全新副本(类似于 CREATE TABLE AS)并重新排列名称以真正摆脱死列占用的空间。
      • @Summer: CLUSTER 重写整个表(加上索引),从而完美地优化它。 VACUUM FULLCLUSTER 之后是多余的。你可能想运行ANALYZE。这个答案不正确(报价除外)。我添加了一个答案来澄清。
      【解决方案3】:

      为什么要“重新排序”? SQL中没有顺序,它没有意义。如果您需要固定顺序,请告诉您的查询您需要什么顺序或使用视图,这就是视图的用途。

      真空后磁盘空间将再次使用,auto_vacuum 将完成这项工作。除非你禁用了这个进程。

      您当前的方法将扼杀整体性能(表锁定),必须重新创建索引,统计数据会被淘汰等等。最终,您会遇到与您一样的情况。那么为什么要努力呢?

      【讨论】:

      • 我期待这会出现。我喜欢我的专栏按照对人类有意义的顺序排列,比如我。只要它不占用太多磁盘空间(在真空满后不会占用)。只是个人喜好。 :)
      • 你不应该依赖隐式列排序,就像你不应该依赖没有 ORDER BY 的查询中的隐式行排序一样。这是否意味着您的应用程序使用 SELECT * 和 INSERT INTO 表 VALUES,而没有字段名称?因为那样只会自找麻烦。如果您需要特定的列顺序,请使用该顺序创建一个视图。
      • 我需要重新排序,因为将某些列分组更容易!我不敢相信 Postgres 不支持这样的基本功能......当然,我不依赖表中列的顺序,但在设计数据库时更容易!为什么所有这些 linux 书呆子都不明白这一点?!现在人们使用GUI!现在是 2011 年!
      • 这个答案在几个方面是不正确的。列的物理顺序有很多含义。不仅在 SELECT * .. 对物理磁盘空间(类型对齐)和性能有副作用 - 即使在大多数情况下并不重要。 postgres 团队具有对待办事项列表中的列重新排序的功能,他们承认其有用性。 OP 表示这是一种罕见的操作,对性能的担忧是错误的。仅仅因为有很多错误的理由来重新排序列,并不是说没有好的理由。声称“SQL 中没有顺序”是完全错误的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-11-07
      • 1970-01-01
      • 2023-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多