打破偏见:Postgres DELETE 其实能扩展

How Postgres DELETE can actually scale

打破偏见:Postgres DELETE 其实能扩展

Postgres DELETE 操作常因性能问题被高性能系统弃用,许多团队选择直接截断表或丢弃分区来清理数据。然而,这种牺牲灵活性的做法并非唯一解。文章深入剖析了 Postgres 基于 MVCC 的删除机制,解释了为何删除看似昂贵,并分享了在 DBOS 处理每秒数万个工作流和步骤的实际场景中,如何通过优化缓存和索引性能,让 DELETE 操作在保持事务隔离和强一致性的同时实现大规模扩展。

如果 DELETE 真的无法扩展,那将是一种遗憾,因为它比丢弃分区或表灵活得多,特别是在数据异构且需要差异化存储期限的场景下。
  1. mike_hearn

    MVCC 的实现方式不必像 Postgres 那样。在某些其他数据库中,像 DELETE 或 UPDATE 这样的写操作会直接在原地覆盖磁盘块,没有行复制也没有 vacuum 操作。为了提供 MVCC,数据库会生成“回滚日志”(undo logs),顾名思义——如果你需要在更早的快照点读取数据库,它会从磁盘读取数据,然后利用回滚数据撤销在你 MVCC 快照之后发生的写入。当没有活跃事务再需要时,回滚数据会被定期丢弃。

    已有补丁试图将 Postgres 改为这种模型,因为它有许多优势——所有因 autovacuum 滞后导致的停机和问题都会消失——但这些补丁从未被合并。

    Oracle 有几个相关特性:

    - 回滚数据可以被保留并用于时间旅行查询(SELECT .. AS OF)。

    - DML 可以并行化,写入主节点可以横向扩展,因此大型 DELETE 操作可以在多台机器上同时运行。不过你需要手动开启:

    ALTER SESSION ENABLE PARALLEL DML;

    DELETE /*+ PARALLEL(t, 8) */

    FROM t

    WHERE created_at < :cutoff;

    COMMIT;

    https://docs.oracle.com/en/database/oracle/oracle-database/2...

    话说回来,博客中讨论的问题并不直接关乎 DELETE 本身处理得多快,而是它对数据库后续性能的影响。

    声明:我在 Oracle 数据库团队兼职。

  2. bob1029

    > 一个分区直到其中存储的每一条数据都不再需要时才能被删除。这对某些系统来说是合适的,比如消息队列,其中数据在可预测的时间内被需要。然而,对于支持长运行工作流的工作流系统来说,这并不合适。

    如果大多数工作流在几天内完成,我们可以显式地将那些长运行的条目向前复制,然后回收整个分区。仅仅因为我们懒得规范化不到 1% 的使用场景,就牺牲一个极佳的技术方案,这似乎相当草率,尤其是当我们考虑到这种对技术简单性的拒绝往往把我们带向何处时。

同日更多故事

2026-10-19