PostgreSQL窗口函数执行更快,因其执行计划更激进地使用哈希聚合与并行扫描,支持索引下推、动态偏移、WINDOW命名复用及WHERE直接过滤;MySQL 8.0依赖临时表排序、不支持动态偏移和并行,每个窗口单独排序,内存管理粗粒度,实测1000万行取最新记录快1.7秒。

PostgreSQL窗口函数执行更快,尤其在多分区、大结果集场景
PostgreSQL的窗口函数执行计划更激进地使用哈希聚合和并行扫描,MySQL 8.0仍依赖临时表+排序,在无索引或高基数PARTITION BY字段时容易触发磁盘临时表。实测1000万行订单表按customer_id分组取最新记录,PostgreSQL耗时2.1秒,MySQL 8.0.32为3.8秒(相同硬件、索引(order_date, customer_id))。
关键差异点:
- PostgreSQL对
ROW_NUMBER() OVER (PARTITION BY x ORDER BY y)能直接利用索引下推,MySQL需先排序再编号 - MySQL不支持
WINDOW命名子句复用定义,重复写OVER()会重复计算 - PostgreSQL允许在
WHERE中直接过滤窗口函数结果(如WHERE rn = 1),MySQL必须套一层子查询
MySQL 8.0窗口函数不支持部分高级语法,PostgreSQL更贴近SQL标准
MySQL至今不支持RANGE BETWEEN中的表达式偏移(如RANGE BETWEEN INTERVAL '7 days' PRECEDING AND CURRENT ROW),而PostgreSQL从9.4起就完整支持。另外,MySQL对LAG/LEAD的offset参数只接受常量,不能是列值;PostgreSQL允许动态偏移。
常见报错示例:
MySQL执行LAG(amount, days_late) OVER (ORDER BY order_date)会直接报错ERROR 3589 (HY000): Window function 'lag' requires a constant offset;PostgreSQL可正常运行。
内存占用与并发表现差异明显
PostgreSQL窗口函数默认启用work_mem控制内存上限,超限时自动降级为外排(disk-based sort);MySQL 8.0用tmp_table_size和max_heap_table_size共同约束,但窗口计算阶段不区分内存/磁盘路径,一旦溢出就整体变慢。
并发压力下要注意:
- PostgreSQL多个窗口查询可共享同一物化中间结果(如
SELECT *, ROW_NUMBER(), RANK() OVER (…)共用排序结果) - MySQL每个窗口函数单独走一遍排序流程,CPU和I/O开销翻倍
- PostgreSQL支持
PARALLEL执行窗口函数(需max_parallel_workers_per_gather > 0),MySQL完全单线程执行
别忽略统计信息更新对执行计划的影响
两者都依赖表统计信息生成窗口函数执行计划,但PostgreSQL对ANALYZE更敏感:若customer_id分布倾斜严重,未及时ANALYZE可能导致哈希分区失衡,反而比MySQL的稳定排序更慢。MySQL优化器对窗口函数的代价估算较保守,有时宁可选慢但确定的路径。
建议操作:
- PostgreSQL执行前确认
SELECT reltuples FROM pg_class WHERE relname = 'orders'与实际行数偏差 - MySQL检查
SHOW INDEX FROM orders中Cardinality是否更新(尤其是复合索引第二列) - 对高频窗口查询的表,PostgreSQL建议开启
track_counts = on并设autovacuum_analyze_scale_factor = 0.01
窗口函数不是“写了就能快”,PostgreSQL的优势需要配合合理的统计信息和资源配置才能释放。MySQL 8.0的限制更多在语法和执行模型层面,短期难改变。



















