【问题标题】:A faster way to copy a postgresql database (or the best way)复制 postgresql 数据库的更快方法(或最佳方法)
【发布时间】:2019-03-21 06:07:10
【问题描述】:

我对数据库进行了 pg_dump,现在正尝试将生成的 .sql 文件安装到另一台服务器上。

我正在使用以下命令。

psql -f databasedump.sql

我今天早些时候启动了数据库安装,现在 7 小时后数据库仍在填充。我不知道这是否应该花多长时间,但我继续监视它,到目前为止,我已经看到超过 12 万个插入和计数。我怀疑有一种更快的方法可以做到这一点。

【问题讨论】:

  • 无论哪种方式,1200 万次插入,通常在中等硬件上只需要一分钟,即使使用 psql 和普通 SQL 转储也是如此。如果花费了 7 个小时,则说明您的设置有问题。
  • 这可能很明显,但请检查您是否没有向转储提供跨数据库兼容性选项--inserts--column-inserts。您还可以检查您的 ASCII 脚本是否使用 COPY 重新加载数据。
  • 有关更多信息,我正在使用 EC2 微实例,因此它有点内存限制。它是 Postgresql 7.4(必须自己编译),因为数据来自旧的 7.4 设置。
  • 也许在更快的硬件上进行恢复,在数据库上做一个完全真空,然后将文件复制到 EC2,例如:使用 rsync。
  • 我遇到了同样的问题(使用 ASP.Net Core),我意识到我的日志记录大大减慢了它。美国邮政编码表的导入只需几秒钟。

标签: postgresql


【解决方案1】:

创建你的转储

pg_dump -Fc -Z 9  --file=file.dump myDb

Fc

输出一个适合输入到 pg_restore 的自定义存档。这是最灵活的格式,因为它允许重新排序加载数据和对象定义。这种格式也是默认压缩的。

Z 9: --compress=0..9

指定要使用的压缩级别。零表示没有压缩。对于自定义归档格式,这指定了单个表数据段的压缩,默认为中等压缩级别。对于纯文本输出,设置非零压缩级别会导致整个输出文件被压缩,就好像它是通过 gzip 输入的一样;但默认是不压缩的。 tar 归档格式目前根本不支持压缩。

并使用恢复它

pg_restore -Fc -j 8  file.dump

-j: --jobs=number-of-jobs

使用多个并发作业运行 pg_restore 中最耗时的部分——加载数据、创建索引或创建约束的部分。此选项可以显着减少将大型数据库恢复到运行在多处理器计算机上的服务器的时间。

每个作业是一个进程或一个线程,具体取决于操作系统,并使用与服务器的单独连接。

此选项的最佳值取决于服务器、客户端和网络的硬件设置。因素包括 CPU 内核的数量和磁盘设置。一个好的起点是服务器上的 CPU 内核数量,但在许多情况下,大于该数量的值也会导致更快的恢复时间。当然,过高的值会因为抖动而导致性能下降。

此选项仅支持自定义和目录归档格式。输入必须是常规文件或目录(例如,不是管道)。发出脚本而不是直接连接到数据库服务器时,将忽略此选项。此外,多个作业不能与选项--single-transaction 一起使用。

链接:

pg_dump

pg_restore

【讨论】:

  • 有时,关闭压缩后 pg_dump 会更快 (-Z0)。显然,转储要大得多。但是,如果您有空间和快速磁盘,这可能是正确的权衡。
  • 如果可以的话,使用外部压缩器的性能要好得多。 pg_dump ... -Fc -Z0 | pigz > file.dump.gz 对我来说比内置压缩快 3 倍,可能是因为内置压缩是单线程的?
  • 添加到 mikv 评论:即使我从 45Mo 转到 5,4Go,它在我的 SSD 上的速度也快了 5 倍。现在时间比大小更重要(哈哈!)。
  • 问题要求“更快的方式”,所以答案不应该使用最大的压缩。
  • 可以和pg_dumpall一起使用吗?
【解决方案2】:

改进 pg 转储和恢复

PG_DUMP |始终使用带有-j 选项的格式目录

time pg_dump -j 8 -Fd -f /tmp/newout.dir fsdcm_external

PG_RESTORE |始终使用带有格式目录的 postgres.conf 调优使用 -j 选项

work_mem = 32MB
shared_buffers = 4GB
maintenance_work_mem = 2GB
full_page_writes = off
autovacuum = off
wal_buffers = -1

time pg_restore -j 8 --format=d -C -d postgres /tmp/newout.dir/`

更多信息

https://gitlab.com/yanar/Tuning/wikis/improve-pg-dump&restore

【讨论】:

  • 有些人可能认为在您的存储库中比较“PG_DUMP 9.6 Fc 格式 VS Fd 格式”很奇怪,但后者得到了一个额外的 -j 8 参数。也许值得添加一个注释,“仅目录格式支持并行备份”。此外,如果您还报告生成的文件大小以进行 Fc/Fd 比较,那就太好了。
【解决方案3】:

为什么要生成原始 .sql 转储? pg_dump的开头描述推荐“自定义”格式-Fc

然后您可以使用 pg_restore 来恢复您的数据(或其中的选定部分)。有一个“作业数量”选项-j 可以使用多个内核(假设您的磁盘还不是限制因素)。在大多数情况下,在现代机器上,您至少可以从中获得一些收益。

现在你说“我不知道这需要多长时间”。好吧,在您完成一些恢复之前,您不会知道。请监控您的系统正在做什么,以及您是否受到 CPU 或磁盘 I/O 的限制。

最后,您想要用于恢复数据库的配置设置并不是您想要运行它的那些。几个有用的启动器:

  1. 增加maintenance_work_mem,以便您可以在更大的块中构建索引
  2. 在恢复期间关闭fsync。如果你的机器崩溃了,你无论如何都要从头开始。

请记住在恢复后重置它们。

【讨论】:

  • 这是非常有用的信息。尽管我过去使用过 Postgresql,但我显然对它一无所知。我发现您的反馈很有启发性。
  • 使用 psql 花了大约 9 个小时。我想使用 pg_restore 进行测试,我应该只运行 pg_restore 还是擦除我的数据目录并从头开始更好(这是一个测试盒,关键任务数据都在 live 盒上)?跨度>
  • 您将需要一个新的转储 (-Fc),然后如果您有磁盘空间,您可以根据需要恢复一个不同名称的数据库。这次计划监控它 - 索引很容易比表数据花费更长的时间。您可能会发现创建一个较小的测试数据库(相同的结构)并多次转储/恢复它以更好地了解事物的交互方式很有用。
【解决方案4】:

pg_dump的用法一般建议搭配pg_restore,而不是psql。这种方法可以通过传递--jobs 标志在内核之间拆分以加快加载过程:

$ pg_restore --jobs=8 dump.sql

Postgres 本身有一个 guide 用于批量加载数据。

我还建议您对postgresql.conf 配置文件进行大量调整,并为maintenance_work_memcheckpoint_segments 值设置适当的高值;较高的值可能会显着提高您的写入性能。

【讨论】:

  • 请不要发布明显错误的信息。如果您不知道问题的答案,请不要回答。您的答案不仅不正确,任何跟随它的人都会发现他们的生活变得更加困难而不是更轻松。
  • 我很抱歉;在我发布答案后我意识到这是非常不正确的。我已尽我所知更新了答案,但如果我对 pg_restore 的理解和使用不正确,我将简单地删除答案。
  • 您编辑的答案似乎更有用。我已经删除了我的反对票。我会删除我的评论,但我认为这个链条没有多大意义。
  • 明白了,谢谢 - 我的思绪一直沉浸在跨多个连接进行分区和加载数据的世界中,因为我的第一个答案只是喋喋不休。漫长的一天...
猜你喜欢
  • 1970-01-01
  • 2010-10-06
  • 2020-08-18
  • 2012-10-30
  • 2015-10-16
  • 2010-09-05
  • 1970-01-01
  • 2011-03-10
  • 1970-01-01
相关资源
最近更新 更多