【问题标题】:Dead Tuples are not being collected by VACCUM FULL CommandVACUUM FULL 命令没有收集死元组
【发布时间】:2023-04-01 18:14:02
【问题描述】:

抱歉,这是很长的帖子和问题以及 postgres 新手

想知道 postgres VACCUMVACCUM FULL 是如何工作的,这对于 700 GB 表存档而不停机是更可取的。

VACCUM FULL CASE:

在这种情况下,看起来在执行 vacuum full 命令后内存正在释放给 OS,但 n_dead_tuples 的大小保持不变。

这个 n_dead_tup 会在下一次插入/更新/删除中重复使用吗?

步骤:

CREATE TABLE Foo (
  id SERIAL PRIMARY KEY,
  x  INTEGER NOT NULL
);

// CREATE TABLE

INSERT INTO Foo (x) VALUES (generate_series(1,1000000));

// INSERT 0 1000000

SELECT pg_size_pretty(pg_relation_size('foo'));

// 35 MB

SELECT n_dead_tup FROM pg_stat_user_tables where relname = 'foo';

// 0

UPDATE Foo SET x = x + 1;

// UPDATE 1000000

SELECT pg_size_pretty(pg_relation_size('foo'));

// 69 MB

SELECT n_dead_tup FROM pg_stat_user_tables where relname = 'foo';

// 1000000

VACUUM FULL VERBOSE foo;

// INFO:  vacuuming "public.foo"
// INFO:  "foo": found 1000000 removable, 1000000 nonremovable row versions in 8850 pages
// DETAIL:  0 dead row versions cannot be removed yet.
// CPU 0.07s/0.67u sec elapsed 0.76 sec.
// VACUUM

 SELECT pg_size_pretty(pg_relation_size('foo'));

// 35 MB

SELECT n_dead_tup FROM pg_stat_user_tables where relname = 'foo';

// 1000000

真空箱

步骤:

除 VACCUM FULL 外与上述步骤相同,需要运行以下命令,在这种情况下,看起来像死元组被删除但大小未释放到操作系统。

VACUUM VERBOSE foo;

// INFO:  vacuuming "public.foo"
// INFO:  scanned index "foo_pkey" to remove 1000000 row versions
// DETAIL:  CPU 0.01s/0.27u sec elapsed 0.34 sec.
// INFO:  "foo": removed 1000000 row versions in 4425 pages
// DETAIL:  CPU 0.00s/0.02u sec elapsed 0.02 sec.
// INFO:  index "foo_pkey" now contains 1000000 row versions in 8237 pages
// DETAIL:  1000000 index row versions were removed.
// 0 index pages have been deleted, 0 are currently reusable.
// CPU 0.00s/0.00u sec elapsed 0.00 sec.
// INFO:  "foo": found 1000000 removable, 1000000 nonremovable row versions in 8850 out of 8850 pages
// DETAIL:  0 dead row versions cannot be removed yet.
// There were 0 unused item pointers.
// Skipped 0 pages due to buffer pins.
// 0 pages are entirely empty.
// CPU 0.03s/0.52u sec elapsed 0.61 sec.
// VACUUM

SELECT pg_size_pretty(pg_relation_size('foo'));

// 69 MB

SELECT n_dead_tup FROM pg_stat_user_tables where relname = 'foo';

// 0

AUTO VACUUM是否等同于VACUUM

提前致谢。

【问题讨论】:

    标签: sql postgresql postgresql-9.4 vacuum


    【解决方案1】:

    简单的VACUUM 通常不会像explained in the documentation 那样释放磁盘空间:

    [...] 但是,额外的空间不会返回给操作系统(在大多数情况下);它只是保留在同一张表中以供重复使用。 [...]

    对于VACUUM FULL则不同,因为它基本上将整个表数据重写为explained in the documentation

    [...] 此方法还需要额外的磁盘空间,因为它会写入表的新副本,并且在操作完成之前不会释放旧副本。 [...]

    通过重写,数据在物理上紧密地写入在一起,没有旧行版本引起的漏洞。所需的磁盘空间不断增长是 PostgreSQL 实现的MVCC 的缺点之一,需要仔细观察和调整大表和更新量大的表。

    自动真空将从不执行VACUUM FULL,因为它会阻止它正在处理的表/关系上的任何其他活动,并对任何连接的应用程序产生不可预测的后果。

    如果您在此处遇到问题,您至少应该开始考虑以维护VACUUM FULL 的影响保持低(因为分区很小)甚至更好的方式对表进行分区,使您能够只需删除一个分区而不需要重写。但这实际上取决于您存储和更新的数据的语义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-28
      • 2018-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多