【问题标题】:delete rows and get space postgresql删除行并获取空间 postgresql
【发布时间】:2018-05-30 10:53:10
【问题描述】:

我对 postgresql 没有那么丰富的经验。

做了一个简单的命令
DELETE FROM table_name where some_condition;

涉及数千行。但是实际上在该命令之后,磁盘空间变得更小了。

知道出了什么问题吗?我启用了 autovacuum = on 并尝试执行 'VACUUM FULL;'但这占用了我的整个磁盘空间。

我想做的很简单。删除行并获取空间。涉及的空间很大,机器上没有那么多空间。有没有办法做到这一点?

【问题讨论】:

    标签: sql postgresql autovacuum


    【解决方案1】:

    autovacuum 应该在 any 现代 Postgres 数据库中运行,除非您确切知道自己在做什么。但 autovacuum 不会缩小表格,除了极少数的极端情况。它会安排定期的VACUUMANALYZE 作业,但从不 VACUUM FULL,它会在已处理的表和索引上获得排他锁。 VACUUM 有助于避免表和索引膨胀,不过,通过清理死元组(以及其他各种善举),从而为同一对象上的未来写入操作提供空间 - 尚未将空间返回给操作系统。

    你写:

    试图执行 'VACUUM FULL;'但这占用了我的整个磁盘空间。

    您的意思是暂时?因为这就是VACUUM FULL 所做的。但是当它完成后,表和相关的索引会减少到它们的最小大小——这通常是不可取的,除非你迫切需要磁盘空间或永远不会更新行。

    所以VACUUM FULL 适合您的工具,除非您的磁盘空间已经用完 - 最好不要一开始就发生这种情况。所以你需要创造一些回旋的空间让它发挥它的魔力。

    还有社区工具pg_repack,可以做到和VACUUM FULL一样,不用排他锁。但它也需要一些可用的磁盘空间才能工作。更多详细信息的相关答案:


    要删除表的所有行并立即释放磁盘空间,请使用TRUNCATE。它有效地在磁盘上写入一个新文件并删除旧文件。这也是为什么它通常不能与数据库上的并发负载一起使用的原因。

    TRUNCATE table_name;
    

    【讨论】:

    • “TRUNCATE [...] 不能与 DB 上的并发负载一起使用”?你的意思是,TRUNCATE 不是MVVC safe
    • @TmTron:是的,就是这样。
    【解决方案2】:

    VACUUM FULL 通过创建每个表的新版本并复制所有数据来工作。在新表完成之前不会删除旧表,因此VACUUM FULL 操作将在处理时临时增加磁盘空间。请参阅 PostgreSQL 文档中的 this note(重点是我的):

    提示:由于大量更新或删除活动导致表包含大量死行版本时,普通 VACUUM 可能无法令人满意。如果您有这样的表并且需要回收它占用的多余磁盘空间,则需要使用 VACUUM FULL,或者 CLUSTER 或 ALTER TABLE 的表重写变体之一。这些命令重写表的全新副本并为其构建新索引。所有这些选项都需要排他锁。 请注意,它们还临时使用大约等于表大小的额外磁盘空间,因为表和索引的旧副本在新副本完成之前无法释放。

    另一方面,普通的VACUUM 只是从数据库文件中删除已删除的行和索引条目。

    如果您先运行普通的VACUUM,然后尝试运行VACUUM FULL,您可能会取得更大的成功。如果您尝试在特定表上运行VACUUM FULL,您可能还会获得更多成功。如果您以正确的顺序运行它们,您可能能够恢复足够的磁盘空间,以便数据库中的剩余表可以运行VACUUM FULL。否则,您将需要找到一些增加可用磁盘空间的方法,以便VACUUM FULL 可以完成。

    【讨论】:

    • 是否有一些解决方法,或者在删除每个 sql 后磁盘空间没有释放的原因是什么?据我了解,如果我想运行这个命令,我需要至少与数据库消耗的空间一样多。将删除语句分块是否有意义,比如分成 1000 个部分然后运行 ​​VACUUM?
    • 磁盘空间不会按设计立即释放。我在上面链接的同一个页面说,“这种方法对于获得多版本并发控制(MVCC,参见第 13 章)的好处是必要的:当行版本仍然可能对其他事务可见时,不得删除它。”
    • 只有VACUUM FULL 需要磁盘空间。 VACUUM 不需要磁盘空间。我猜想批量删除后跟定期VACUUMs 对您目前的情况没有帮助,但也许我缺少一些东西。我不是 PostgreSQL 方面的专家。
    • 您可以在 PostgreSQL 中启用autovacuum daemon,它会定期清理过时的已删除行和索引。建议您使用它。不知道是不是默认开启的。
    • 好的,我明白了。所以我认为如果启用它,我只需要等待。有没有办法查明该守护进程是否正在运行以及它现在在做什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-23
    • 2020-06-04
    相关资源
    最近更新 更多