PostgreSQL 19: 支持 TID 范围扫描的并行化

John Doe 一月 14, 2026

PostgreSQL 从版本 9.6 开始支持并行查询,到 PostgreSQL 19 基本已经将并行化落实到了查询执行的各个角落。

image

特性提交日志

为 TID 范围扫描添加并行化支持

在 PostgreSQL 14 版本中,已经通过引入专用的执行器节点,实现了对元组标识符(TID)范围扫描的支持。本次在此基础上,进一步实现了该类扫描的并行化处理。TID 范围扫描的块区间划分方式,与并行顺序扫描(Parallel Seq Scan)的处理逻辑类似:系统会将待扫描的数据块划分为若干“数据块组”,并分配给各个工作进程;随着扫描接近尾声,每个工作进程所分配到的数据块组规模会逐步缩减,直至最终每个进程仅处理单个数据块。这种设计可确保所有工作进程基本同步完成任务。

实现 TID 范围扫描的并行化,能够解决优化器此前面临的决策困境。在并行全表扫描与非并行 TID 范围扫描之间抉择时,优化器需要权衡二者的成本:并行全表扫描借助 CPU 并行能力提升效率,但磁盘 I/O 成本不会随工作进程数量的增加而分摊;而非并行 TID 范围扫描虽能精准定位目标数据块,却无法利用多核优势。此前,优化器有可能会选择并行全表扫描,这反而会导致执行过程中读取额外的数据块,造成不必要的开销。而并行化 TID 范围扫描的落地,消弭了优化器的取舍难题,无需再在“并行化带来的 CPU 成本降低”与“并行全表扫描因扫描非目标 TID 范围数据块而产生的额外 I/O 开销”之间权衡。当然,这项改进也能带来并行技术固有的性能红利,其优势在此便无需赘述。

示例

利用并行 TID 范围扫描,在减少 IO 的同时利用多核 CPU,快速获取目标订单数据。

1. 确认 TID 范围(假设已通过分区键查询到目标数据的 TID 范围):

-- 先通过业务条件获取 TID 范围
SELECT min(ctid), max(ctid) FROM orders
  WHERE create_time BETWEEN '2024-10-01' AND '2024-10-07';
   min     |    max
-----------+------------
 (50000,0) | (60000,199)

2. 执行并行 TID 范围扫描:

-- 开启并行
SET max_parallel_workers_per_gather = 4;

-- 执行查询
EXPLAIN ANALYZE SELECT order_id, user_id, amount, create_time
  FROM orders WHERE ctid BETWEEN '(50000,0)' AND '(60000,199)';

3. 执行计划分析:

 Parallel Tid Range Scan on orders  (cost=0.00..2890.32 rows=250000 width=48) (actual time=0.15..12.36 rows=248567 loops=4)
   TID Range: [(50000,0)..(60000,199)]
   Workers Planned: 3
   Workers Launched: 3
 Planning Time: 0.31 ms
 Execution Time: 18.72 ms

扫描仅覆盖 10001 个块(50000~60000),避免全表 10 万个块的 IO 浪费;

启动 3 个 worker 进程并行处理,执行时间从非并行的 65ms 缩短至 18.72ms,性能提升 3.5 倍。

在保证 IO 高效的前提下,通过多核并行大幅缩短查询时间,满足数据分析场景的高效数据提取需求。

参考

提交日志:https://git.postgresql.org/pg/commitdiff/0ca3b16973a8bb1c185f56e65edcadc0d9d2c406