不完全来自这本书,把查到的和之前的文章重新汇总整理了一把。
参考:PostgreSQL: Feature Matrix
例外命令:以下语句可以在查询部分用到并行 CREATE TABLE ... AS,SELECT INTO,CREATE MATERIALIZED VIEW,REFRESH MATERIALIZED VIEW
SELECT * FROM pg_proc WHERE proparallel = 'u';
计划中可并行部分越多,潜在的性能增益就越大。然而,某些操作仅能由leader进程严格顺序执行,即使它们本身不会干扰并行化。换句话说,它们不能出现在Gather节点下面的计划树中。
最明显的案例是扫描CTE结果(在计划中表示为CTE扫描节点):
如果CTE部分没有物化,执行计划不包括CTE scan节点,则不会应用此限制
SELECT * FROM pg_proc WHERE proparallel = 'r';
几个容易弄混的进程和参数,关系图如下
Background workers Processes:
虽然名字里也带Background字样,但它不包含SysLogger,Bgwriter,WaLWriter等系统后台进程,主要是动态启动的进程:例如并行查询进程,插件的后台进程等,即图中蓝绿色部分
max_parallel_workers代表的是最多的worker数量,设置为1代表有1个worker,加上主进程一起其实并行度为2;设置为0,才会只有主进程,才是串行。它其实是主进程最多可以fork的进程数量?如果最多可以fork出一个,实际上是有两个进程
Workers Launched: 1 不代表是串行,而是主进程fork了一个子进程,加上主进程一起其实并行度为2
三个参数大小关系为
max_worker_processes>=max_parallel_workers>=max_parallel_workers_per_gather
并行最小表大小取决于min_parallel_table_scan_size参数,除非创建表时指定了并行参数,否则小表不用并行。计算公式为:
这意味着每当表增大3倍,就会多用一个并行进程(不超过上限时):
一些案例
如果取消限制,则能使用3个进程
如果将max_parallel_workers限制为5,并且执行两个上面语句,其中一个实际只能分配到两个worker,因为3+2已经达到5的上限
强制使用并行
在本例中factor是2.4,行数预估算法
SELECT reltuples::numeric, round(reltuples / 2.4) AS per_process FROM pg_class WHERE relname = 'bookings';
预估算法
SELECT round((relpages * current_setting('seq_page_cost')::real +reltuples / 2.4 * current_setting('cpu_tuple_cost')::real)::numeric, 2) FROM pg_class WHERE relname = 'bookings';
WITH t(startup_cost)
AS (SELECT 22243.29 + round((reltuples / 2.4 * current_setting('cpu_operator_cost')::real)::numeric, 2) FROM pg_class WHERE relname = 'bookings')
SELECT startup_cost,startup_cost + round((1 * current_setting('cpu_tuple_cost')::real)::numeric, 2) AS total_cost FROM t;
Gather节点由leader进程执行,负责启动worker进程并收集它们返回的数据。
就执行计划而言,启动进程的成本估计(无论其数量如何)由parallel_setup_cost参数定义,进程之间每传输1行的成本估计为parallel_tuple_cost。
在这个例子中,启动成本(用于启动进程)占优势;这个值会被添加到Partial Aggregate节点的启动成本中。总成本还包括传输两行的成本,被添加到Partial Aggregate节点的总成本中。
SELECT 24442.36 + round(current_setting('parallel_setup_cost')::numeric,2) AS setup_cost,
24442.37 + round(current_setting('parallel_setup_cost')::numeric +2 * current_setting('parallel_tuple_cost')::numeric,2) AS total_cost;
Finalize Aggregate节点汇总了Gather节点从并行进程中接收到的所有结果。
它的启动成本基于汇总三行的成本;这个值会被添加到Gather节点的总成本中(因为需要所有行才能计算结果)。Finalize Aggregate的总成本还包括返回一行的成本。
WITH t(startup_cost) AS (SELECT 25442.57 + round((3 * current_setting('cpu_operator_cost')::real)::numeric, 2) FROM pg_class WHERE relname = 'bookings')
SELECT startup_cost,startup_cost + round((1 * current_setting('cpu_tuple_cost')::real)::numeric, 2) AS total_cost FROM t;
成本估计之间的依赖关系取决于节点是否需要在将结果传递给父节点之前累积数据。
启动并行worker的cost,启动并行worker需要建立共享内存等操作,属于额外成本,默认为1000。
pg 10新增(9.6版本名为min_parallel_relation_size),开启并行的条件之一,表占用空间小于此值可能不会开启并行,并行顺序扫描场景下扫描的数据大小通常等于表大小,默认值8MB。
注意还有其他条件决定是否启用并行,所以并不是小于它的表就一定不会启用并行。
pg 10新增,开启并行的条件之一,实际上并行扫描不会扫描索引所有数据块,只是扫描索引相关数据块,默认值512KB。
强制开启并行,可以用于测试,也可以作为hint,OLTP生产环境不建议开启。
并行分区表分区聚合
并行HASH计算
并行分区表JOIN
LEADER主动获取并行WORKER的返回结果
并行APPEND(分区表),UNION ALL查询
前面都是数据库的参数,parallel_workers是表级参数,可以在建表时设置,也可以后期设置。
参考
初探PostgreSQL中的并行
PostgreSQL 9.6 并行计算 优化器算法浅析-阿里云开发者社区
PostgreSQL: Feature Matrix
PostgreSQL 11 并行计算算法,参数,强制并行度设置-阿里云开发者社区
Postgresql 并行查询原理与实践_pg并行查询_瀚高PG实验室的博客-CSDN博客