请教一个问题,PG 15 表中某列使用alter table alter column调整大小时发现[阿里云PolarDB]

请教一个问题,PG 15 表中某列使用alter table alter column调整大小时发现,字段变长felfilenode不变,字段变短relfilenode会变化。PG在这种情况下为什么会重建数据文件呢?谢谢

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
=====这是一个广告位,招租中,联系qq 78315851====
7 条回复 A 作者 M 管理员
  1. 在 PostgreSQL 中,ALTER TABLE ALTER COLUMN 语句用于修改表中的列定义。当你改变列的长度时,可能会导致存储空间的变化,这会影响到表的数据文件和索引文件。
    在 PostgreSQL 中,每个表都有一个主数据文件,称为 relfilenode,它存储了表中的数据。当你增加列的长度时,如果新数据的长度超过了原数据在磁盘上占用的空间,那么 relfilenode 可能会变化。
    另一方面,当你缩短列的长度时,原来占用的空间可能会被浪费。为了充分利用空间,PostgreSQL 可能会将新的数据写入到新的 relfilenode 中。因此,在这种情况下,relfilenode 可能会变化。
    至于 felfilenode,这是表的元数据,存储在 pg_class 表中,用于表示表和它的索引之间的关系。它通常不会随着列长度的调整而改变。如果从分区或子分区中删除了大量的行,或者对一个带有可变长度的行(即存在VARCHAR、BLOB或TEXT类型的列)进行修改,可以使用ALTER TABLE … OPTIMIZE PARTITION来回收任何未使用的空间和整理分区数据文件的碎片。

  2. 楼主你好,在 PostgreSQL 中,每个表都对应着至少一个数据文件,即 relfilenode。当你使用 ALTER TABLE ALTER COLUMN 命令修改某一列的大小时,如果缩小了列的大小,那么存储该列的数据的空间就会减小,这就会导致原有的数据块不再能够容纳所有的数据,因此需要重新分配更小的块。而如果增大了列的大小,那么原有的数据块仍然可以满足要求,因此不需要重新分配数据块。

    因此,当你使用 ALTER TABLE ALTER COLUMN 命令缩小某列大小时,PG需要重新分配更小的数据块,因此会创建新的数据文件来存储数据,同时原有的数据文件会被删除。而当你增大某列的大小时,原有的数据文件仍然可以满足要求,因此不需要重新创建数据文件。

    需要注意的是,当使用 ALTER TABLE ALTER COLUMN 命令修改某列的大小时,PG可能会进行表重建操作,这会导致数据文件的更改。因此你需要在修改表结构之前备份数据。

  3. 当使用ALTER TABLE ALTER COLUMN命令调整表中某列的大小时,PostgreSQL(PG)在以下情况下会重建数据文件:

    1. 变长字段增加大小:如果您将变长字段的大小增加,例如从VARCHAR(100)增加到VARCHAR(200),PG需要为每个行插入更多的数据空间。由于原始数据文件的大小是固定的,所以PG需要创建一个新的数据文件,并将数据从旧文件复制到新文件中,以便为每个行提供足够的空间。

    2. 变长字段减小大小:相比之下,如果您将变长字段的大小减小,例如从VARCHAR(200)减小到VARCHAR(100),PG不需要重建数据文件。因为减小大小不需要为每个行插入更多的数据空间,原始数据文件的大小可以适应新的字段大小。

    关于字段变短(如VARCHAR(200)变为VARCHAR(100))时relfilenode的变化,这是因为PG采用了一种称为TOAST(The Oversized-Attribute Storage Technique)的机制来处理大型或变长的字段。TOAST会根据字段的实际大小来决定是否对其进行压缩,并将它们存储在单独的TOAST表中。当您通过ALTER TABLE ALTER COLUMN命令调整字段大小时,PG可能会重新组织TOAST表,并分配新的relfilenode以适应新的字段大小。

  4. 表发生重写了,举例来说varchar(200)改varchar(20),这种场景就会重写表,filenode会变化。反之就不会。

    此答案来自钉钉群“PG|POLARDB技术进阶”


  5. 我已经认真阅读了 你的问题:

    【 请教一个问题,PG 15 表中某列使用alter table alter column调整大小时发现

    并思考了

    建议如下:


    在 PostgreSQL 中,当使用 ALTER TABLE ALTER COLUMN 语句调整列的大小时,如果列变长,PostgreSQL 会自动重建数据文件。这是因为数据文件的大小是按照列的顺序分配的,如果列变长,那么原本分配给该列的空间就需要重新分配。
    这种情况下,PostgreSQL 会创建一个新的数据文件,并将原数据文件中的数据复制到新的数据文件中。在这个过程中,原来的数据文件会被删除。这是因为在 PostgreSQL 中,数据文件是按照列的顺序存储的,如果列顺序发生变化,那么原有的数据文件就无法继续使用。
    相反,如果列变短,PostgreSQL 不会重建数据文件。因为列变短意味着需要的空间减小,原本分配给该列的空间可以继续使用。
    需要注意的是,在调整列大小时,尤其是将列变长时,可能会导致性能下降。因为数据文件的重建是一个 I/O 密集型的操作,可能会消耗大量的时间和资源。因此,在调整列大小时,建议尽可能地预测未来的数据增长,避免频繁地调整列大小。

  6. 在 PostgreSQL 中,当你使用 ALTER TABLE 命令修改表的列大小时,实际上是在修改表的元数据(metadata),而不是修改表的数据本身。这个元数据包括每个列的名称、类型、大小等信息。当你修改列大小时, PostgreSQL 会根据新的大小重新计算并分配表的存储空间,这可能会导致原来的数据文件大小不再适合新的列大小,因此 PostgreSQL 会重建数据文件以适应新的列大小。
    对于 felfilenode 和 relfilenode,它们是指文件在磁盘上的物理位置,而不是文件大小。因此,当你修改列大小时,这些值可能会发生变化,因为 PostgreSQL 需要重新分配表的存储空间,并且可能会选择不同的文件布局和大小。这些变化是正常的,并不一定意味着数据文件已经被重建。

  7. PG在字段变短时重建数据文件的原因是为了确保数据的完整性和一致性。当字段变短时,原有的数据文件可能会包含超出新字段长度的数据,这可能导致数据的截断或者损坏。为了避免这种情况发生,PG会选择重建数据文件,将超出新字段长度的数据删除或者截断,以保证数据的正确性。这样做虽然会增加一些额外的开销,但可以确保数据的完整性。

  8. 当使用 ALTER TABLE ... ALTER COLUMN 语句调整列的大小时,PostgreSQL(PG)的行存储引擎会根据以下情况进行重建数据文件:

    1. 字段变长:如果你将字段的最大长度增加,超出了原始大小,则需要进行重建数据文件。这是因为增加字段的最大长度可能导致原始数据行不再适应新的大小限制,因此必须重新分配足够的空间来容纳更长的值。

    2. 字段变短:如果你将字段的最大长度缩小,并且缩小后的最大长度小于原始大小,则字段的数据可能需要被截断到新的大小。为了执行此操作,PG需要重建数据文件,以确保所有行的数据都符合新的大小限制。

    在上述两种情况下,PG需要重新组织数据文件,以适应修改后的表结构。这涉及到创建一个新的数据文件(称为新的relfilenode),然后将数据从旧的数据文件复制到新的文件中,同时对数据进行相应的调整。

    这种重建数据文件的过程可能会对性能产生一定的影响,特别是针对大表或有大量数据的表。因此,在对表进行结构更改时,建议在低负载时期进行操作,并在可能的情况下考虑避免频繁地更改字段的大小。