假删除:PostgreSQL的删除操作是否真实有效?

发表时间: 2023-12-19 15:45

1、问题现象

pg中一张表A无效数据比较大,我需要dump出来整个数据库,我执行删除A表 delete无效数据后,查看数据库磁盘空间大小无变化。难道PostgreSQL delete 是标记删除?

2、直接上答案,解密PG delete操作底层做了啥

show me code

在 PostgreSQL 中,DELETE 操作本身是逻辑上的删除操作,也可以称为标记删除。这意味着 DELETE 操作并不会立即从数据库中物理删除数据行,而是将其标记为已删除。已删除的行仍然占据磁盘空间,并且可以通过 VACUUM 运行时进行回收。

删除操作背后的原理是基于 PostgreSQL 的多版本并发控制(MVCC)机制。当执行 DELETE 时,PostgreSQL 将为表中的每一行创建一个新版本,并且在新版本中通过标记将其标记为已删除。这样,其他并发事务仍然可以访问表中的旧版本数据,而执行 DELETE 的事务只能访问新版本(不包含已删除的行)的数据。

要永久删除已标记删除的行并回收磁盘空间,需要执行 VACUUM 操作。VACUUM 会清理已删除的行版本,并将空间释放回数据库文件系统。

delete 操作

需要注意的是,DELETE 操作的速度相对较快,因为它只涉及逻辑删除,而不是实际的物理删除。然而,数据库的性能可能会受到已删除行的累积影响,这时需要定期运行 VACUUM 来清理并优化数据库。

3、vacuum 到底是个啥?

VACUUM是PostgreSQL中的一个辅助进程,主要负责完成两个主要任务:

  • 删除死元组(Dead Tuples):删除无用的元组数据所占用的空间。
  • 冻结事务ID(Freezing Tansaction IDs):必要时冻结老元组的Txid,以防止因事务ID的重置而导致非常老的数据丢失。

VACUUM有助于PostgreSQL的持久运行,释放因更新或删除而被占用的磁盘空间,更新查询计划中使用的统计数据,并提供分析统计信息以提高其他模块的性能。

4、vacuum 性能开销大吗?

VACUUM 操作的性能开销取决于许多因素,包括表的大小、数据分布、硬件性能以及需要执行的具体操作。通常来说,VACUUM 操作对性能的影响相对较小,尤其是在小规模表或定期执行的情况下。

先写日志 再刷磁盘

然而,对于大型表或在高并发环境下执行 VACUUM 操作可能会对性能产生一定的影响。在这种情况下,你可以考虑以下几点来最小化性能开销:

1、定期执行 VACUUM:根据表的活动水平和数据变化频率,定期执行 VACUUM 操作,而不是频繁执行。

2、选择适当的时间:选择在系统负载较低的时间执行 VACUUM 操作,以避免对并发操作造成影响。

3、调整 VACUUM 参数:根据具体情况,你可以调整 VACUUM 的参数,如真空程度(VACUUM FULL 与 VACUUM ANALYZE)和并发性限制,以平衡性能和维护需求。

4、使用分区表:如果表很大,可以考虑使用分区表,将数据分布在多个分区上。这样可以将 VACUUM 操作分散到各个分区上,提高执行效率。

总的来说,VACUUM 操作的性能开销通常是可以接受的,但对于大型表或高并发环境,需要谨慎考虑执行时间和参数设置,以确保对系统性能的影响最小化。

5、vacuum full 命令

VACUUM FULL 是 PostgreSQL 中的一种 VACUUM 命令的变体,它在执行 VACUUM 操作的同时还对表进行完全重建。与普通的 VACUUM 命令相比,VACUUM FULL 的主要特点和行为不同:

完全重建表:VACUUM FULL 运行过程中会将表重新创建,并将所有数据重新写入到新的文件中。这个过程类似于将表导出为一个临时文件,然后重新导入到一个新的表中,以达到整理和压缩数据库文件的目的。

占用更多的时间和资源:由于进行完全重建的特性,VACUUM FULL 操作通常需要更长的时间和更多的系统资源,尤其是在处理大型表时。因此,建议在数据库空闲或低负载时执行。

数据库锁定:在运行 VACUUM FULL 过程中,表会被独占锁定,其他对表的读写操作将被阻塞,直到 VACUUM FULL 完成。

由于 VACUUM FULL 涉及到重建整个表,所以在正常情况下,使用普通的 VACUUM 命令已足够维护数据库的性能和空间使用。只有在特定情况下,比如大量删除了表数据后数据库文件过度膨胀,可以考虑使用 VACUUM FULL 来进行整理和压缩。

倒车 请注意

请注意,在运行 VACUUM FULL 之前,请确保您已备份了重要的数据,并且明确了操作的风险和影响。