为什么 VACUUM ANALYZE 不清除所有死元组?

jwa*_*ack 8 postgresql vacuum postgresql-9.3

VACUUM ANALYZE VERBOSE在对一些较大的表进行重大DELETE/INSERT更改后,我们会在它们上运行“手册” 。这似乎没有问题,尽管有时表的VACUUM工作会运行数小时(有关类似问题和推理,请参阅此帖子)。

在进行更多研究后,我发现即使在运行VACUUM. 例如,以下是此响应中查询生成的一些统计信息。

-[ RECORD 50 ]--+---------------------------
relname         | example_a
last_vacuum     | 2014-09-23 01:43
last_autovacuum | 2014-08-01 01:19
n_tup           |    199,169,568
dead_tup        |    111,048,906
av_threshold    |     39,833,964
expect_av       | *
-[ RECORD 51 ]--+---------------------------
relname         | example_b
last_vacuum     | 2014-09-23 01:48
last_autovacuum | 2014-08-30 12:40
n_tup           |    216,596,624
dead_tup        |    117,224,220
av_threshold    |     43,319,375
expect_av       | *
-[ RECORD 52 ]--+---------------------------
relname         | example_c
last_vacuum     | 2014-09-23 01:55
last_autovacuum | 2014-09-23 18:25
n_tup           |    309,831,136
dead_tup        |    125,047,233
av_threshold    |     61,966,277
expect_av       | *
Run Code Online (Sandbox Code Playgroud)

最后一个字段指出这些(和大多数表)将满足 autovacuum 的阈值。但是,刚刚VACUUM ANALYZE VEBOSE在每个表上运行,死元组计数不应该是 0(或接近 0,而不是 300M 中的 125M)吗?

文件指出:

VACUUM 回收被死元组占用的存储空间。

这是否意味着我们VACUUM的不工作?


更新

这里的响应中的每个请求是来自VERBOSE作业的一些日志:

INFO:  vacuuming "public.example_1"
INFO:  scanned index "idx_example_1_on_gp_id_and_dd_id" to remove 378386 row versions
DETAIL:  CPU 1.83s/3.42u sec elapsed 23.01 sec.
INFO:  scanned index "index_example_1_on_q_id" to remove 378386 row versions
DETAIL:  CPU 2.10s/3.91u sec elapsed 18.92 sec.
INFO:  "example_1": removed 378386 row versions in 7085 pages
DETAIL:  CPU 0.09s/0.05u sec elapsed 0.19 sec.
INFO:  index "idx_example_1_on_gp_id_and_dd_id" now contains 30347438 row versions in 291065 pages
DETAIL:  378386 index row versions were removed.
165587 index pages have been deleted, 164287 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  index "index_example_1_on_q_id" now contains 30347438 row versions in 333287 pages
DETAIL:  378386 index row versions were removed.
152773 index pages have been deleted, 152757 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "example_1": found 1773 removable, 401984 nonremovable row versions in 14438 out of 1493006 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 10567 unused item pointers.
0 pages are entirely empty.
CPU 4.26s/7.51u sec elapsed 46.10 sec.
INFO:  vacuuming "pg_toast.pg_toast_17917"
INFO:  index "pg_toast_17917_index" now contains 0 row versions in 1 pages
DETAIL:  0 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:  "pg_toast_17917": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.example_1"
INFO:  "example_1": scanned 30000 of 1493006 pages, containing 611502 live rows and 0 dead rows; 30000 rows in sample, 40563141 estimated total rows
Run Code Online (Sandbox Code Playgroud)

此表现在在统计信息中显示 0 个死元组。今天早上大多数表都是低得多的死元组,所以我们的VACUUM或 autovacuum 都在工作。

我们确实有一些不输出任何内容但仍然显示死元组的表:

-[ RECORD 49 ]--+---------------------------
relname         | example_2
last_vacuum     | 2014-09-23 02:23
last_autovacuum | 2014-09-02 14:30
n_tup           |    117,914,944
dead_tup        |     34,507,388
av_threshold    |     23,583,039
expect_av       | *
Run Code Online (Sandbox Code Playgroud)

有几次我在日志中看到索引会被一遍又一遍地检查。这似乎对应于长时间运行的VACUUM作业。知道为什么吗?这是否只是解决记录锁定问题(我认为在此作业运行期间没有发生任何写入。)

INFO:  vacuuming "public.example_2"
...
INFO:  scanned index "index_example_2_on_gsg_id_and_dd_id" to remove 2795959 row versions
DETAIL:  CPU 3.88s/16.54u sec elapsed 23.09 sec.
INFO:  scanned index "index_example_2_on_q_id" to remove 2795959 row versions
DETAIL:  CPU 6.74s/21.13u sec elapsed 84.64 sec.
INFO:  "example_2": removed 2795959 row versions in 48214 pages
DETAIL:  CPU 0.71s/0.32u sec elapsed 33.65 sec.
INFO:  scanned index "index_example_2_on_gsg_id_and_dd_id" to remove 2591011 row versions
DETAIL:  CPU 2.84s/16.11u sec elapsed 19.28 sec.
INFO:  scanned index "index_example_2_on_q_id" to remove 2591011 row versions
DETAIL:  CPU 5.46s/22.70u sec elapsed 130.57 sec.
INFO:  "example_2": removed 2591011 row versions in 45539 pages
DETAIL:  CPU 0.67s/0.38u sec elapsed 15.16 sec.
INFO:  index "index_example_2_on_gsg_id_and_dd_id" now contains 123807784 row versions in 1560915 pages
DETAIL:  108836958 index row versions were removed.
1100790 index pages have been deleted, 718471 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.25 sec.
INFO:  index "index_example_2_on_q_id" now contains 123807784 row versions in 1886087 pages
DETAIL:  110336259 index row versions were removed.
1058063 index pages have been deleted, 266983 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.07 sec.
INFO:  "example_2": found 124808 removable, 1355901 nonremovable row versions in 2086343 out of 6966379 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 7858495 unused item pointers.
0 pages are entirely empty.
CPU 595.49s/2130.13u sec elapsed 5656.34 sec.
INFO:  vacuuming "pg_toast.pg_toast_18079"
INFO:  index "pg_toast_18079_index" now contains 0 row versions in 1 pages
DETAIL:  0 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:  "pg_toast_18079": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.example_2"
INFO:  "example_2": scanned 30000 of 6966379 pages, containing 528443 live rows and 522 dead rows; 30000 rows in sample, 152953760 estimated total rows
Run Code Online (Sandbox Code Playgroud)

jja*_*nes 10

VACUUM 只能删除长期死掉的死元组,也就是说,对所有可能的用途都是死的。如果您有长期存在的事务,它们可能会阻止删除最近死亡的元组。

这是一个长期事务阻止删除的情况示例:

INFO:  "pgbench_accounts": found 0 removable, 2999042 nonremovable row versions in 49181 out of 163935 pages
DETAIL:  2999000 dead row versions cannot be removed yet.
Run Code Online (Sandbox Code Playgroud)

它不是真正的长期事务,而是长期存在的快照。当然,长时间运行的 select 或 insert 语句会做到这一点。对于高于读提交的隔离级别,整个事务将保留快照直到它关闭,因此如果某些人打开一个可重复读的事务然后休假而不提交它,那将是一个问题。挂起准备好的事务也是如此(如果您不知道什么是准备好的事务,那么您可能没有使用它们)。

你展示的例子并不表示有问题,但你也说到那时问题已经解决了。如果这是一个反复出现的问题,您可能应该开始记录 VACUUM VERBOSE 语句的输出,以便您可以找到涵盖问题存在期间的信息。

多次通过索引是因为您的 maintenance_work_mem 设置。每次遍历索引时,它只能为每 6 个字节的内存删除一个元组,如果需要删除更多,则需要进行多次传递。所以增加maintenance_work_mem 会有所帮助。


Erw*_*ter 5

VACUUM表的物理大小通常不会通过运行(或)来减小(除了从表末尾机会性地修剪可移动页之外)VACUUM ANALYZE。您需要运行VACUUM FULL才能实际收缩表。

以上是相关答案的引用,其中有更多细节:

手册(实际上就在您的报价下方):

Plain VACUUM(不带FULL)只是回收空间并使其可供重复使用。这种形式的命令可以与表的正常读写并行操作,因为没有获得排他锁。但是,额外的空间不会返回给操作系统(在大多数情况下);

更多这里:

您将对pg_repackpg_squeeze感兴趣,它们可以在没有独占锁的情况下压缩表。


归档时间:

查看次数:

13249 次

最近记录:

10 年,12 月 前