并行查询执行
来自 PostgreSQL wiki
跳转到导航跳转到搜索目的
Postgres 目前在客户端代码中支持完全并行。应用程序可以打开多个数据库连接并异步管理它们,或通过线程管理它们。
在服务器端,已经存在一些并行性
- effective_io_concurrency 允许对内核进行表页预取请求,用于位图连接
- 服务器端语言可能可以执行并行操作
好处
并行性有三种可能的好处
- 使用多个 CPU
- 使用多个 I/O 通道(用于顺序和随机 I/O)
- 使用多个 CPU 和 I/O 通道
方法
有几种方法可以添加并行性
- 使用 fork(或 Windows 上的线程——我认为它也是一个进程,而不是线程;线程共享地址空间,进程不共享)并且只调用 libc 和特定于并行的函数来执行并行计算或 I/O(这仅仅是读取操作吗?)。这避免了尝试使现有后端代码线程安全的问题。我们是否需要等到能够在后端进程之间共享事务?
- 与上面相同,但修改一些现有的后端模块以支持 fork/线程安全,无论是否具有共享内存访问;这可能允许整个执行器节点树并行运行
- 创建可以并行执行查询部分并返回结果的完整后端
- 创建一个等待并行请求的后端池
- 初始方法可能从修改单个计划节点开始,以便在执行器中并行运行。最终,我们需要教育计划程序和优化器如何对并行化查询进行建模。
挑战
寻找合适的任务:要将并行性添加到单线程任务中,该任务必须能够被分解成足够大的部分并独立执行。(如果子部分太小,执行并行的开销会超过并行的好处。)不幸的是,与 GUI 应用程序不同,Postgres 后端通过执行许多必须按顺序执行的小任务来执行查询,例如解析器、计划程序、执行器。——可以有人记录我在哪里可以得到关于这三个阶段中每个阶段花费时间的量化数据吗?我们能提供给用户参与指标收集吗?
这意味着数据库只允许在有限的情况下进行并行,主要是针对那些可能变为 CPU 或 I/O 绑定的大型查询。例如,基于主键选择一行不太可能从并行中获益。相反,大型查询通常可以从并行中获益。
返回数据:另一个挑战是从辅助进程/线程中返回数据。对于像 SUM() 这样的东西,它很容易,但将大量数据传回可能很复杂。
避免开销:并行性有自己的成本,因此需要有一种方法来控制何时使用并行执行。
限制过度并行性:还需要某种机制来检测其他会话的并行性,以确保不会超过 CPU 和 I/O 资源。
具体机会
并行机会包括
- 表空间
- 分区
- 外部表
- 多表访问
- 连接(例如嵌套循环)、CTE、UNION
- 对 1GB 段文件进行顺序扫描
- 每页可见性检查和元组过滤
- 聚合
- 数据导入/导出
- COPY(以减少解析的 CPU 开销)
- 索引构建
- 约束检查
- 昂贵的函数,例如 PostGIS
PargreSQL [1] 和 [2] 该论文描述了 PargreSQL 并行数据库管理系统 (DBMS) 的架构和设计,该系统适用于分布式内存多处理器。PargreSQL 基于 PostgreSQL 开源 DBMS,并利用分区并行性