【问题标题】:PostgreSQL. Can run update query in parallel?PostgreSQL。可以并行运行更新查询吗?
【发布时间】:2012-10-07 12:17:18
【问题描述】:

我有一张有 1000 万行的大桌子。我需要为每一行获取一些统计值。我有生成这个值的函数,例如GetStatistic(uuid)。这个函数工作很慢,结果值不经常变化,所以我在我的表中创建了列Statistic,并且每天执行一次这样的查询:

UPDATE MyTable SET Statistic = GetStatistic(ID);

在选择查询中,我使用列 Statistic 而不调用 GetStatistic 函数。

问题是,我的生产服务器有 64 个 CPU 和大量内存,所以几乎所有 DB 都可以缓存到 RAM,但这个查询只使用一个 CPU,需要 2 或 3 个小时来执行。

GetStatistic 函数使用表,在UPDATE 查询的所有执行过程中保持不变。我可以修改查询以让 postgre 使用所有可用的 CPU 同时为不同的行并行计算 GetStatistic 吗?

【问题讨论】:

  • 为什么要使用函数,有什么是普通SQL无法完成的吗?该函数是否只需要来自当前行的值,还是还涉及其他数据源(:=tables)?顺便说一句:向我们展示函数。
  • 查看这个查询的计划,你会看到这个函数被调用了10M次。也许用纯 SQL 编写会更好,而且速度会更快。

标签: postgresql parallel-processing sql-update


【解决方案1】:

早于 10 的 PostgreSQL 版本在单个后端执行每个查询,该后端是具有单个线程的进程。它不能使用多个 CPU 进行查询。它在单个查询中可以实现的 I/O 并发性也有所限制,实际上只为位图索引扫描执行并发 I/O,否则依赖操作系统和磁盘系统进行并发 I/O。

PostgreSQL 10+ 支持parallel query。在撰写本文时(PostgreSQL 12 版本)并行查询仅用于只读查询。并行查询支持为某些类型的查询提供了相当多的并行性。

Pg 擅长并发负载许多较小的查询,并且很容易以这种方式使您的系统饱和。它只是不擅长为一两个非常大的查询充分利用系统资源,尽管随着为更多类型的查询添加并行查询支持,这种情况正在改善。


如果您使用的是没有并行查询的旧 PostgreSQL,或者您的查询尚未受益于并行查询支持:

您可以做的是将工作分成几块并将它们分发给工人。你已经暗示了这一点:

我可以修改查询以让 postgre 并行计算 GetStatistic 使用所有可用的 CPU 同时处理不同的行?

有多种工具可以帮助完成此类工作,例如 DBlinkPL/ProxypgbouncerPgPool-II。或者,您可以自己做,启动(比如说)8 个工作人员,每个工作人员都连接到数据库并使用不重叠的 ID 范围执行 UPDATE ... WHERE id BETWEEN ? AND ? 语句。一个更复杂的选择是让队列控制器将大约 1000 个 ID 的范围分发给 UPDATE 该范围的工作人员,然后请求一个新的。

请注意,64 个 CPU 并不意味着 64 个并发工作人员是理想的。在写入方面,您的磁盘 I/O 也是一个因素。如果您将UPDATE 事务设置为使用commit_delay 和(如果您对此数据的业务要求安全)synchronous_commit = 'off',那么您可以降低 I/O 成本,那么同步的负载应该会显着减少。尽管如此,最好的吞吐量很可能远低于 64 个并发工作人员。

很有可能您的GetStatistic 函数可以通过将其转换为可内联的 SQL 函数或视图来加快速度,而不是目前可能是循环繁重的过程 PL/pgSQL 函数。如果您显示此功能可能会有所帮助。

【讨论】:

猜你喜欢
  • 2018-08-06
  • 1970-01-01
  • 2019-08-25
  • 1970-01-01
  • 2012-06-27
  • 1970-01-01
  • 1970-01-01
  • 2012-07-05
  • 1970-01-01
相关资源
最近更新 更多