除了真空之外,死行是否被其他任何东西移除?

Are dead rows removed by anything else than vacuum?

在 PostgreSQL 9.3.19 日志中,我看到以下两个连续的给定 table 的 autovacuum 条目:

2018-06-29 17:24:06 CDT 13177 14/870454 0 LOG:  automatic vacuum of table "openbravo.public.ad_session_status": index scans: 0
    pages: 0 removed, 235 remain
    tuples: 0 removed, 14669 remain
    buffer usage: 1090 hits, 673 misses, 4 dirtied
    avg read rate: 6.745 MB/s, avg write rate: 0.040 MB/s

--

2018-06-29 17:24:55 CDT 13529 40/699086 0 LOG:  automatic vacuum of table "openbravo.public.ad_session_status": index scans: 0
    pages: 0 removed, 235 remain
    tuples: 0 removed, 13039 remain
    buffer usage: 1143 hits, 663 misses, 0 dirtied
    avg read rate: 3.086 MB/s, avg write rate: 0.000 MB/s

All autovacuums are logged: log_autovacuum_min_duration=0.

中间没有其他手动吸尘器。

如果这两个 vacuum 中的 none 正在删除任何死元组,那么剩余的元组数量会在第 2 个之后减少吗? PostgreSQL 是否有其他方法来删除死行?

一种解释可能是 HOT updates

如果 table 块中有空间并且没有更新的列被索引,PostgreSQL 将把新行版本放在与原始行相同的块中,并创建一个“HOT 链”,其中旧行版本指向新的。这允许 PostgreSQL 跳过更新指向此 table 行的所有索引。

除了在 UPDATE 期间减少 I/O 之外,HOT 还允许“即时”删除旧行版本:每当访问几乎已满的页面时,可以对其进行必要的锁定获得后,PostgreSQL 将通过重组对该块执行“微真空”。

这可能导致观察到的元组减少。

为了支持或反驳这一理论,运行 查询如下:

SELECT n_tup_upd, n_tup_hot_upd
FROM pg_stat_user_tables
WHERE schemaname = 'public' AND relname = 'ad_session_status';

如果 n_tup_hot_upd 大于零,我们有一个案例。