抱歉,这是一篇很长的帖子,也是问题和postgres的新手
想知道postgres VACCUM 和 VACCUM FULL 的工作原理,这对于700 GB的表归档没有停机时间是更可取的。
真空情况:
在这种情况下,似乎在执行vacuum full命令之后将内存释放到OS,但是n_dead_tuples保持相同大小。
此n_dead_tup会在下一次插入/更新/删除时重用吗?
STEPS:
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
真空箱
STEPS:
除了VACCUM FULL以外,与上述步骤相同,需要运行以下命令,在这种情况下,看起来像死元组已被删除,但是大小未释放到OS。
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
自动真空是否等于真空?
谢谢。
答案 0 :(得分:1)
简单的VACUUM
通常不会像explained in the documentation那样释放磁盘空间:
[...]但是,在大多数情况下,不会将多余的空间返回给操作系统。它只是可以在同一张表中重复使用。 [...]
对于VACUUM FULL
来说有所不同,因为它基本上将整个表数据重写为explained in the documentation:
[...]此方法还需要额外的磁盘空间,因为它会写入表的新副本,并且在操作完成之前不会释放旧副本。 [...]
通过重写,数据在物理上紧密靠近地写入,而不会因较旧的行版本引起空洞。所需的不断增加的磁盘空间是PostgreSQL实现的MVCC的缺点之一,需要仔细观察和调整大表和更新繁重的表。
自动抽真空将从不执行VACUUM FULL
,因为它会阻止正在处理的表/关系上的任何其他活动,从而对任何连接的应用程序造成不可预测的后果。
如果您在此处遇到问题,则应至少考虑以以下方式对表进行分区:维护VACUUM FULL
的影响保持较低(因为分区的大小很小),甚至更好,启用您只需删除一个分区而不需要重写。但这实际上取决于您要存储和更新的数据的语义。