为什么在“完成”后真空等待完全等待?

时间:2017-01-18 22:47:03

标签: postgresql postgresql-9.3 vacuum

我在一张很大的桌子上抽真空。

当我运行时,它说:

bacula=# VACUUM FULL VERBOSE file_partition_19
bacula-# ;
INFO:  vacuuming "public.file_partition_19"
INFO:  "file_partition_19": found 16242451 removable, 21024161 nonremovable row versions in 900380 pages
DETAIL:  0 dead row versions cannot be removed yet.
CPU 5.14s/14.42u sec elapsed 19.61 sec.
VACUUM
Time: 163784.767 ms
bacula=# 

当它执行此操作时,它会很快显示到CPU行,然后在显示最后两行(+提示)之前等待很长时间。这反映在时间上的差异 - “经过19.61秒”,与“时间:”163秒相比(因为我设置了\timing on)。

虽然我还没有计时,但两次都是正确的 - 启动命令,等待20秒,然后显示“CPU”行,然后等待大约3分钟,然后打印其余部分。

这是正常的吗?为什么会这样?

2 个答案:

答案 0 :(得分:3)

它主要重建桌面上的所有表现,因为它基本上已经完成了#34; VACUUM FULL"完全重写表格。如果你从表中删除所有的indizes,那么在" CPU"之后几乎没有延迟。线。

AFAICT,CPU使用率行由通用例程打印,该例程执行其他(非FULL)真空模式的大部分工作。在" VACUUM FULL"中没有任何意义。情况下。

如果您担心需要太长时间,我建议您查看" When to use VACUUM FULL and when not to"来自PostgreSQL wiki。当人们使用VACUUM FULL时,他们实际上不应该有10次中有9次。

答案 1 :(得分:2)

基于您用于问题的“postgres-9.3”标签,我假设你有Postgres 9.3版本。

你可以参考这个链接,仅仅是为了你对9.0版之前Postgres的“VACUUM”和“VACUUM FULL”的了解。

<强> VACUUM VS VACUUM FULL For Pre-9.0 versions of Postgres

因为你有Postgres-9.3,文档说如下:

  

为清楚起见,9.0更改VACUUM FULL。如文档中所述,VACUUM FULL实现已更改为与旧版本中使用CLUSTER类似的实现。这给出了与此处描述的旧VACUUM FULL略有不同的权衡取舍。虽然通过此更改消除了通过索引膨胀使数据库速度变慢的可能性,但由于VACUUM FULL的锁定和一般性能开销,您仍可能希望避免这样做。

根据当前文档,VACUUM FULL操作不仅从记录被标记为已删除的表中检索空间,而且还触及表中的每个有效记录并尝试在DB页面中重新组织它们以便它如何释放更多空间然后只是VACUUM操作。所以当我们看到行

时,在VERBOS结果中
CPU 5.14s/14.42u sec elapsed 19.61 sec

系统进程通过表并分析表并检索已标记的空间所花费的时间。然后它开始将记录组织成页面文件,因此根据表格页面的碎片数量,这个过程需要时间。

例如,如果您有一个新表并继续按增量/顺序添加新记录,以便在页面底部添加新记录(基于定义的主键)。现在,您以相反的顺序执行删除操作,以便仅从页面底部删除记录。假设你从表中删除了一半的记录。在这种情况下,没有太多页面碎片(实际上是0),因此当VACUMME FULL运行第二阶段时,它仍将尝试组织有效记录,但因为没有碎片,因此它不必实际移动任何记录并且会更快完成。

但是,上面解释的情况不是现实世界中更新/删除的方式。表格上的真实单词更新/删除会产生大量页面碎片,因此在第二阶段,VACUUM FULL过程必须在每页开头将实际有效记录移动到可用空间,因此需要更多时间。

检查以下示例输出

VACUMM FULL Output

我跑了很小的假桌子。即使它只有7行。 VACUME PROCESS (第一阶段)以0.03秒(30毫秒)结束,但总查询报告为在61毫秒内完成。所以这告诉我即使没有什么可以重新组织过程仍然检查它可以重组多少,因此需要时间。但是,如果我实际上有很多碎片并进行重组,那么根据页面碎片的不同,完成时间会更长。