9

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

当我运行它时,它说:

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 分钟,然后打印其余部分。

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

4

2 回答 2

4

它主要是重建表上的所有索引,它必须这样做,因为基本上“VACUUM FULL”会完全重写表。如果从表中删除所有索引,“CPU”行之后应该几乎没有延迟。

AFAICT,CPU 使用线由通用例程打印,该例程为其他(非 FULL)真空模式完成大部分工作。在“VACUUM FULL”情况下是没有意义的。

如果您担心它花费的时间太长,我建议您查看 PostgreSQL wiki 中的“何时使用 VACUUM FULL 以及何时不使用”。当人们使用 VACUUM FULL 时,10 次中有 9 次实际上不应该使用。

于 2017-02-01T19:26:13.130 回答
2

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

您可以参考此链接,以了解有关 Postgres 9.0 之前版本的“VACUUM”和“VACUUM FULL”的知识。

VACUUM VS VACUUM FULL 对于 9.0 之前的 Postgres 版本

因此,当您拥有 Postgres-9.3 时,文档说明如下:

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

根据当前文档,VACUUM FULL 操作不仅从表中检索记录被标记为已删除的空间,而且还触及表中的每条有效记录并尝试在数据库页面中重新组织它们,这样它就可以释放更多空间,然后只是真空操作。所以当我们看到这条线时,在 VERBOS 结果中

CPU 5.14s/14.42u sec elapsed 19.61 sec

它是系统进程遍历表并分析表并检索已标记的空间所花费的时间。然后它开始将记录组织到页面文件中,因此取决于有多少表页面被分割,该过程将花费时间。

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

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

检查以下示例输出,

VACUMM 全输出

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

于 2017-02-01T22:26:48.203 回答