使用 Postgres 11.1,我一直在尝试确定/估计表中将由 VACUUM FULL 恢复的“浪费”空间量。我的计划是使用 pg_stat_get_live_tuples (L)、pg_stat_get_dead_tuples (D) 和 pg_total_relation_size (S),然后估计浪费的空间为 (D / (L+D)) * S。
但是,这似乎不起作用。在调查为什么不这样做时,我进行了以下设置:
CREATE TABLE sam_silly(txt TEXT);
INSERT INTO sam_silly VALUES('one');
INSERT INTO sam_silly VALUES('two');
INSERT INTO sam_silly VALUES('three');
INSERT INTO sam_silly VALUES('four');
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
INSERT INTO sam_silly SELECT txt || '+' FROM sam_silly;
然后我根据这些功能对空间进行了初步统计。结果符合预期(有一百万行,即 2^20 行):
select pg_total_relation_size(c.oid) AS size, pg_stat_get_live_tuples(c.oid) AS live, pg_stat_get_dead_tuples(c.oid) AS dead
FROM pg_class c where relname='sam_silly';
- 47308800, 1048576, 0
然后我删除了一半的表:
delete from sam_silly where txt like 'one%' or txt like 'three%';
立即重复上面的查询给出了我期望的结果:
- 47308800, 524288, 524288
一半的数据是活的,一半是死的。
然后我运行“分析”,这就是事情变得奇怪的地方:
- 47316992, 524288, 0
空间略有上升,但现在没有死行!
我也试过“真空”:
- 47316992, 524264, 0
变化不大。
最后,在 VACUUM FULL 之后,它的行为再次符合我的预期:
- 23519232, 524264, 0
现在没有死元组,而且空间已经恢复。
真正的数据库打开了 autovacuum,所以它可能会清理我感兴趣的表。但看起来清理会导致它将死元组的数量设置为 0,即使仍然有很多“浪费”的空间。
有没有办法找出/估计在这种情况下“浪费”了多少空间,当 pg_stat_get_dead_tuples 返回零时,即使它没有回收先前报告的死元组使用的空间?
相关情况下的确切版本:“x86_64-pc-linux-gnu 上的 PostgreSQL 11.1,由 gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28) 编译,64 位”