Postgres中针对单个连接的查询并行化

6
我知道在PostgreSQL中,多个连接会使用多个CPU核心并且并行运行。但是当我执行一个长时间运行的查询,比如说30秒(假设无法进一步优化),输入/输出会被阻塞,而且不会从相同的客户端/连接中运行任何其他查询。
这是设计上的问题还是可以改善的呢?
因此,我认为运行长时间查询的最佳方式是获取新连接或者在同一连接中不运行任何其他查询直到该查询完成。

2
这是按设计实现的,目前无法更改。如果您想要并行工作,您需要打开第二个连接。即使Postgres能够在后端为单个查询使用多个核心,启动该查询的连接仍将被阻塞。 - user330315
我认为这可能会回答你的问题:https://dev59.com/BGgu5IYBdhLWcg3wDS4G - mustaccio
这并没有完全回答我的问题,但提供了更多的见解,谢谢。@a_horse_with_no_name:所以我的假设在这里是正确的,如果它是一个长时间运行的查询,如果连接便宜/不运行任何需要快速处理的相同连接中的查询,则在新连接上运行它? - Greedy Coder
编辑后请发表评论。现在有意义了。谢谢 :) - Greedy Coder
1个回答

7

这是一个设计限制。

PostgreSQL 每个连接使用一个进程,每个进程有一个会话。每个进程都是单线程的,并通过从 postmaster 继承的 fork() 重度使用全局变量。共享内存是显式管理的。

这在开发、调试和维护方面具有一些很大的优势,并使系统在面对错误时更加健壮。然而,在查询级别上添加并行化变得更加困难。

目前正在进行添加并行查询支持的工作,但现在该系统实际上仅限于每个查询使用一个 CPU 核心。它可以从某些区域的并行 I/O 中受益,例如位图索引扫描(通过 effective_io_concurrency),但在其他区域中则不能。

有一些我认为相当 hacky 的解决方法,比如 PL/Proxy,但大多数情况下,如果需要并行化,则必须自己处理客户端。这正迅速成为影响 PostgreSQL 的更显著的限制之一。应用程序可以将大型查询拆分成多个影响数据子集的小型查询,然后统一到客户端(或进一步处理到未记录表中),即 Map/Reduce 风格的模式。如果需要混合大型长时间运行的查询和低延迟 OLTP 查询,则需要多个连接,并且该应用程序通常应使用内部连接池。


1
如果你要实现手动并行,你可能会发现对主表进行分区是有帮助的(当然,所有关于分区的常规警告仍然适用)。 - David Aldridge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接