暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

[译]如何将数据插入数据库 - 尽可能快

原创 Ellison 2022-06-28
388

原文地址:https://www.depesz.com/2007/07/05/how-to-insert-data-to-database-as-fast-as-possible/


前段时间我在 postgresql 8.2 中写了一篇关于 values(),() 的文章,说多行插入非常快。

有人说我的基准测试毫无用处,因为我没有考虑交易。

其他人要求我将文本翻译成英文。

所以我决定重做测试,用更多的测试场景,并用英文写出来。这是总结。

起初我使用了什么,我测试了什么以及如何。

我使用了一台linux机器,里面有这些东西:

  • cpu: AMD Sempron(tm) 处理器 2600+ (1.6ghz)
  • 内存:3GB
  • 光盘:4 250gb hitachi sata 光盘(仅使用了一张)

我试图使机器尽可能可预测,因此我停止了所有不必要的守护进程。结果 tar 文件中提供了完整的 ps auxwwf 输出。基本上——有 postgresql、sshd、openvpn、dhclient 和一些 getty。没有 cron、atd、smtpd、httpd 或类似的东西。

然后我写了一个生成测试文件的小程序。我自己不分发测试文件,因为它们总共使用了将近 70gb!

然后我写了另一个小程序——它基本上运行了所有的测试(3次取平均值)。

全套结果可作为 tar 文件下载,其中包含 10598 个文件(tar 文件为 350k,解压后的目录需要 42megs)。

一个非常重要的通知。我执行的所有测试都将随机数据插入到此结构的表中:

  • id int4 主键,
  • some_text 文本,
  • bool_1 布尔值,
  • bool_2 布尔值,
  • some_date 日期,
  • some_timestamp 时间戳

所以结果(尤其是没有进一步增益的“断点”)在插入另一个表时会有所不同。这个基准测试的唯一要点是显示哪种方法可以给出哪些结果。以及真正值得麻烦的是什么从一些角度来看,我测试了标准 postgresql 中可用的最快方式——复制,而最慢的方式——大量单行插入,没有事务,没有准备。

复制数据:

  • 17.02 秒
  • 1451 cpu 在用户模式下
  • 191 cpu 在系统模式下
  • iowait 中的 20.67 cpu

(CPU 单元是“USER_HZ”,如 linux 内核文档中的 filesystems/proc.txt.gz 文件中所述)。

简单的插入:

  • 622.66 秒
  • 43208 cpu 处于用户模式
  • 14175 cpu 处于系统模式
  • iowait 中的 64.33 cpu

哇。这是相当不同的复制时间大约是插入时间的 2%。我想知道我们可以用不同的插入物得到多接近这 2%。

所以,让我们看看如果我使用事务会变得更好。

插入时间.png

正如我们所看到的,使用事务可以将处理速度提高到 425-430 秒左右。这提供了大约 32% 的提升。cpu使用率如何?

插入百分比.png

从图中我可以推断出 iowaits 在某种程度上是随机的,所以我不会在下一个图表中显示它们(毕竟,我真正对总时间感兴趣)。

最大的收益体现在系统 CPU 使用率上。原因?我有一些理论,但没有一个是基于确凿的事实

无论如何 - 似乎通过在事务中放入 25 个插入来获得可观的收益。在此之上 - 仍有一些收益,但不是很明显。

好的,现在让我们检查一下准备插入语句是否会带来任何好处。

准备好的插入时间.png

它肯定更快。让我们看看加速:

准备好的插入百分比.png

(百分比是针对最简单的插入,没有准备,没有事务)。

可以看出,添加准备会节省一些时间和一些 cpu 使用率,所以这显然是个好主意。使用 prepare 和 inserts 我们可以将时间减少到原始时间的 60% 左右。这还不错。

可以做的最后一件事是使插入在一次调用中插入更多行。

因为我们知道准备工作很好,所以我将只显示准备好的语句的结果。

多插入1.png

不同的行显示单个语句插入的不同行数。

这张图片显示(我希望如此)(就像简单的插入一样)交易奖励只持续一段时间——每笔交易最多 25 条语句。

如果向单个语句添加额外的行没有进一步的好处,那又如何呢?

多插入2.png

不同的行显示每个事务的不同数量的语句。

每次插入多行时,没有明确的“加速结束”。至少在这个测试中没有。

所以,让我们做一个总结。

  • 复制在 17.02 秒内完成了这项工作
  • 最简单的插入在 622.66 秒内完成
  • 在事务中对插入进行分组的最佳方法是每个事务 80 次插入,它使用了 426.81 秒
  • 在自动提交模式下准备好的插入在 545.23 秒内完成了这项工作
  • 在事务中对准备好的插入进行分组的最佳方法——每个事务也有 80 个插入,使用时间为 348.38 秒。
  • 最简单的多行插入(每次插入 5 行,没有准备好的语句,自动提交)在 164 秒内完成了这项工作
  • 插入多行的最佳方法是每个语句使用 100 行,每个事务 100 条语句,使用准备好的语句——它在 37.73 秒内完成了工作。
  • 最好的多行插入,没有事务或准备好的语句——每条语句 100 行。使用时间 – 42.07 秒!

所以,如果你想尽可能快地插入数据——使用复制(或者更好——pgbulkload)。如果由于某种原因您不能使用复制,则使用多行插入(8.2 中的新功能!)。然后如果可以的话,将它们捆绑在事务中,并使用准备好的事务,但通常——它们不会给你太多。

所有其他数据——请查看带有结果的电子表格(openoffice 格式,42k

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论