[](https://res.cloudinary.com/practicaldev/image/fetch/s--i2xAKkHN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1。 medium.com/max/1024/1%2AgvIC2B_kDnWb4honBErXeA.jpeg)

我在整个过程中的感受

最初发布于procrastinatingdev.com

最近我坐下来在我们的开发环境中加快我们的数据库恢复过程。像大多数项目一样,我们的数据库开始时很小,多年来显着增长。当我们启动时,数据库只有几 MB 未压缩。现在压缩了将近 2GB(未压缩 50GB)。我们平均每周恢复一次开发环境,旧的恢复方式不再有效。当我看到“DB restore foos?”在我们的 Slack 频道中,我知道是时候解决这个问题了。

以下是我加快数据库恢复的过程。

天真的方法

下面基本上是我们的第一个备份和恢复版本。在我们的主 Postgres 数据库上,我们将运行一个简单的 pg_dump 并将输出通过管道传输到 gzip。当我们想恢复我们的开发环境时,我们会 SCP 压缩文件,解压缩,然后通过 psql 命令加载它。

$ pg_dump db | gzip > dump.gz

real 7m9.882s
user 5m7.383s
sys 2m56.495s

$ gunzip dump.gz

real 2m27.700s
user 1m28.146s
sys 0m41.451s

$ psql db < dump

real 30m4.237s
user 0m21.545s
sys 0m44.331s

naive 方法的总时间:39 分 41 秒(32.5 分钟恢复开发)

这在很长一段时间内运作良好。当我们的数据库只有几百 MB 时,它简单、易于设置并且速度很快。显然,32.5 分钟来恢复你的开发数据库是不可接受的。

管道解压

我最初加快恢复时间的想法是使用zcat将压缩文件直接通过管道传输到 psql 命令中。您可以将 zcat 视为与cat命令相同,但用于压缩文件。它解压缩文件并将其打印到标准输出,然后您可以将其通过管道传输到您的 psql 命令中。

$ pg_dump db | gzip > dump.gz

real 7m9.882s
user 5m7.383s
sys 2m56.495s

$ zcat dump.gz | psql db

real 26m22.356s
user 1m28.850s
sys 1m47.443s

总时间:33 分 31 秒(26.3 分钟恢复开发,快 20%)

太好了,这使整个过程加快了 16%,实际恢复速度提高了 20%。因为 I/O 是一个瓶颈,所以不写入磁盘为我们节省了 6 分钟多的时间。总的来说,虽然我还是不开心。在恢复我们的开发数据库上浪费了 26 分钟,这还不够好,我不得不走得更远。

自定义格式

当我深入研究pg_dump 文档时,我注意到默认情况下,pg_dump 导出一个纯文本 SQL 文件。正如您在上面看到的,我们然后将其压缩以使其更小以存储它。 Postgres 提供了一种自定义格式,默认情况下使用 zlib 对其进行压缩。我最初的想法是,如果 Postgres 已经以纯文本格式将文件写入磁盘,那么让 Postgres 同时压缩它会更快,而不必将其通过管道传输到 gzip。

由于这种自定义格式,我不得不切换到使用pg_restore,因为您无法使用 psql 重定向压缩文件。

$ pg_dump -Fc db > dumpfc.gz

real 6m28.497s
user 5m2.275s
sys 1m16.637s

$ pg_restore -d db dumpfc.gz

real 26m26.511s
user 0m56.824s
sys 0m15.037s

总_时间 32 分 54 秒(26.4 分钟恢复开发)。_

我认为实际的备份过程会更快,因为我们不必将输出通过管道传输到 gzip,因此我的想法是正确的。不幸的是,在您的本地机器上恢复这种自定义格式并没有使这个过程变得更快。回到绘图板。

指定作业

当我深入研究一个问题时,我总是做的第一件事就是阅读文档和源代码。 Postgres 具有出色的文档,其中包含清晰的布局和标签选项。这些选项之一是能够指定在 pg_restore 执行最耗时的部分、加载数据、创建索引或创建约束时并发运行的作业数量。

pg_restore 文档说,从并发作业数量开始的一个好地方是使用机器上的核心数量。我的开发环境 VM 有 4 个内核,但我想看看不同的值在运行时有什么不同。

$ pg_dump -Fc db > dumpfc.gz

real 6m28.497s
user 5m2.275s
sys 1m16.637s

$ pg_restore -d db -j 2 dumpfc

real 25m39.796s
user 1m30.366s
sys 1m7.032s

总时间 32 分 7 秒,(25.6 分钟恢复 dev 比普通 pg_restore 快 3%)。

好吧,这是一个很小的改进,我们可以再推动一下吗?

$ pg_dump -Fc db > dumpfc.gz

real 6m28.497s
user 5m2.275s
sys 1m16.637s

$ pg_restore -d db -j 4 dumpfc.gz

real 22m6.124s
user 0m58.852s
sys 0m34.682s

总时间 28 分 34 秒(22.1 分钟恢复开发比两个作业快 14%)。

非常好,指定四个作业超过两个可将整体还原时间加快 14%。在这一点上,我们已经从开发环境中的 32.5 分钟加快到 22.1 分钟,增加了 32%!

我现在的想法是我能把这个数字推到多远?

$ pg_dump -Fc db > dumpfc.gz

real 6m28.497s
user 5m2.275s
sys 1m16.637s

$ pg_restore -d db -j 8 dumpfc.gz

real 16m49.539s
user 1m1.344s
sys 0m39.522s

总时间 23 分 17 秒(16.8 分钟恢复开发,比四个作业快 24%)。

因此,将作业数量指定为核心的两倍已将时间从 22.1 分钟减少到 16.8 分钟。在这一点上,我将整个恢复时间加快了 49%,这太棒了。

我可以更进一步吗?

$ pg_dump -Fc db > dumpfc.gz

real 6m28.497s
user 5m2.275s
sys 1m16.637s

$ pg_restore -d db -j 12 dumpfc.gz

real 16m7.071s
user 0m55.323s
sys 0m36.502s

总时间 22 分 35 秒(16.1 分钟恢复开发,比 8 个作业快 4%)。

指定 12 个并发作业确实会稍微加快进程,但总体上会影响 VM 的 CPU 使用率,以至于在恢复过程中它不会过度使用。在这一点上,我确定了 8 个工作或将核心数量翻倍作为最佳使用数量。

最后的想法

最后,我们的活动时间几乎减少了一半,从 30 分钟减少到 16 分钟。 这为我们每年节省超过 72 小时的恢复时间(6 位开发人员,每年 52 次恢复,14 分钟)。总的来说,我对这些变化非常满意。将来我将只关注恢复数据而不是整个数据库,看看这有多快。

In加速 Postgres 恢复第 2 部分我们进一步改进了时间,将其缩短到 5 分钟。


最初发布于procrastinatingdev.com

Logo

CI/CD社区为您提供最前沿的新闻资讯和知识内容

更多推荐