fgb*_*ist 4 postgresql performance upsert
我已经尝试对内置 upsert (INSERT ... ON CONFLICT UPDATE ...) 的性能影响进行了一段时间的研究,当进行了大量 upsert 时。规模大约是每小时 100 万条记录,分为每组大约 300 条记录。
该表相当简单,只有几个 int/bool 字段和一个日期字段。该表的总大小介于 50-6000 万条记录之间。本质上,所有行都应该在某个周期(目前大约为 2 天)内保持最新。有时很多信息会发生变化,有时很少/没有信息变化(例如 300 条记录被更新,但它们与现有记录相同)。
到目前为止,一个假设是,这个项目似乎正在遭受不断发生的大量写入的痛苦,因为即使 upsert 导致没有插入/更新,来自 upsert 的“失败”插入仍然会被写入某个地方(根据我们的知识)。因此,我们的想法是利用老式的 upsert(可写 CTE)并执行更精细的操作,以确保仅插入尚不存在的数据,并且仅更新实际更改的数据。然而,这自然会给数据库带来更多的读取负载并增加查询的复杂性。
问题是,从性能的角度来看,内置 upsert 是无用的(例如,它只适用于更小的任务),我们的假设是正确的,还是我们错了?我阅读了一些关于 HOT 更新和 autovacuum 调整的内容,但没有任何内容引用与此问题更相似的内容。
值得一提的是,这个数据库(PostgreSQL 10.9)在 Heroku 上运行,所以我们无法根据需要对其进行调整。我们计划在某个时候搬家,这取决于它最终的重要性。最后,还值得一提的是,这个DB还有一个follower(即只读副本)。
真的很感激对此有一些好的见解!先谢谢了。
Lau*_*lbe 12
INSERT ... ON CONFLICT
是更新数据的最快方式。如果它对您来说足够快,则只能从性能测试中看出。
如果您使用ON CONFLICT DO NOTHING
或使用UPDATE
子句,这很重要:
使用DO NOTHING
,将不会有任何需要清理的死元组。如果你执行一个UPDATE
,就会有一个死元组,清理这些死元组可能会成为你处理的瓶颈。
使用fillfactor
70 左右的 a 并确保没有更新的列都被索引。然后您可以获得热更新,这可能会节省您的时间。