PostgreSQL 16窗口函数不支持并行执行,ROW_NUMBER()、SUM() OVER()等均走单线程排序路径;提速关键在于绕过排序瓶颈、避免work_mem不足导致的磁盘溢出,并严格匹配索引顺序与PARTITION BY+ORDER BY字段。

PostgreSQL 16 的窗口函数仍不支持并行执行,ROW_NUMBER()、SUM() OVER () 等全部走单线程排序路径——这不是配置问题,是内核限制。提速关键不在“开并行”,而在绕过排序瓶颈、压住落盘、用好索引。
怎么确认是不是 work_mem 不够导致窗口变慢
窗口函数慢,八成是 work_mem 不足触发磁盘排序。别猜,直接看证据:
- 运行
EXPLAIN (ANALYZE, BUFFERS),检查WindowAgg或Sort节点是否出现Sort Method: external merge Disk - 查实时内存用量:
SELECT sort_bytes FROM pg_stat_progress_sort WHERE pid = <your_query_pid></your_query_pid>;若值持续 > 当前work_mem,说明已溢出 -
pg_stat_progress_hash对窗口无效,别查它
如何安全调大 work_mem 避免翻车
窗口函数的内存压力是乘数级的:一个含 PARTITION BY a ORDER BY b 和 RANK() OVER (PARTITION BY c ORDER BY d) 的查询,会同时启动至少两套独立排序,每套都吃一份 work_mem。
PostgreSQL 18.4 官方 Ubuntu 安装包现已发布,这是目前最新的稳定版本。推荐通过官方 APT 仓库安装:先执行 sudo apt update 更新索引,再运行 sudo apt install postgresql-18 即可完成部署。新版本引入了异步 I/O 子系统,在顺序扫描与 VACUUM 场景下性能提升显著,同时支持 UUID v7 原生生成函数与虚拟生成列。
- 起始值建议
SET LOCAL work_mem = '16MB';仍落盘再试'32MB'、'64MB' - 超过
'128MB'要算账:并发 5 个这类查询 × 64MB = 320MB 内存占用,别让系统开始 swap - 别改全局
postgresql.conf——报表类查询才需要大内存,OLTP 请求会被拖垮 - 在应用中用
BEGIN; SET LOCAL work_mem = '64MB'; SELECT ...; COMMIT;最稳妥;若用 PgBouncer,确认ignore_startup_parameters = work_mem已启用
为什么加了索引还不走?
索引不是加了就生效,必须匹配窗口定义且统计信息最新:
- 索引列顺序必须严格对应:
PARTITION BY a ORDER BY b→ 索引需为ON t(a, b) INCLUDE (c)(INCLUDE可覆盖 SELECT 列,避免回表) - 执行
VACUUM ANALYZE t更新统计信息,否则优化器可能忽略索引,继续全表扫描 - 增量排序(Incremental Sort)只对同一
ORDER BY需求连续生效,不同窗口的排序无法复用;嵌套窗口或多个OVER子句仍各自排序
哪些窗口能真正并行?别被标题骗了
PostgreSQL 16 官方文档和源码里没有 “窗口函数并行” 的实现项。所谓“并行”仅指两类场景:
- 无
ORDER BY的聚合类:如COUNT(*) OVER (PARTITION BY x)、AVG(y) OVER (PARTITION BY x),靠max_parallel_workers_per_gather+enable_parallel_tuplestore = on触发 - 带
ORDER BY的窗口,即使设了parallel_leader_participation = off,也仅在work_mem充足且数据分布极均匀时 fallback 尝试,并非常态 -
ROW_NUMBER()、LAG()、SUM() OVER (ORDER BY ... ROWS BETWEEN ...)这些强依赖全局序号或物理偏移的,一律单线程
最常被忽略的点:窗口函数性能瓶颈从来不是 CPU,而是内存与磁盘 I/O 的博弈;调参之前,先看 Sort Method 是不是 Disk —— 这一步漏掉,后面所有优化都是空中楼阁。

















