SQL数据库聚合执行路径_单阶段与多阶段

13次阅读

sql聚合操作执行路径分单阶段与多阶段,取决于数据规模、并行能力、内存限制及优化器决策;单阶段在单节点完成哈希聚合,适用于小数据;多阶段含Partial与Final聚合,用于分布式大数据场景。

SQL数据库聚合执行路径_单阶段与多阶段

SQL数据库中的聚合操作(如 countSUMGROUP BY)执行路径是否走单阶段还是多阶段,主要取决于数据规模、并行能力、内存限制以及查询优化器的决策,而非语法本身。

单阶段聚合执行路径

单阶段聚合指所有分组与计算在同一个执行节点(或单个算子)中完成,通常适用于小数据集或本地执行场景。

  • 典型场景:表数据量小(如万级以下)、无分布式环境(如 sqlite、单机 mysql)、或显式禁用并行(SET parallel_setup_cost = 999999
  • 执行流程:扫描全表 → 建立哈希表(key=分组列,value=聚合值)→ 一次遍历完成累加 → 输出结果
  • 优势是延迟低、无网络/序列化开销;但易受内存限制,大数据量下可能触发磁盘哈希(spill),反而变慢

多阶段聚合执行路径

多阶段聚合将聚合拆分为局部聚合(Partial Aggregate)和全局聚合(Final Aggregate)两个及以上阶段,常见于分布式或并行查询引擎(如 postgresql 并行查询、spark SQL、Presto/Trino、clickhouse)。

  • 第一阶段(Partial):各 worker 独立扫描数据分片,对本地数据做初步聚合(如 COUNT(*) → COUNT(*)_partial
  • 第二阶段(Merge/Final):将各 partial 结果按 group key 重新分发(Shuffle),再合并(如 SUM(count_partial)
  • 部分引擎支持三阶段(如先 local + shuffle + final),用于高基数 GROUP BY 场景,缓解 shuffle 压力

影响执行路径的关键因素

优化器不会随意选择阶段数,而是基于代价模型权衡。以下因素直接影响判断:

  • 数据分布与分组基数:低基数(如按“省份”分组)倾向单阶段;高基数(如按“用户ID”分组且亿级)更可能启用多阶段避免内存爆炸
  • 并行度配置:PostgreSQL 中 max_parallel_workers_per_gather > 0 且表足够大时,GROUP BY 可能自动转为 partial + final
  • 聚合函数性质:可分割聚合(SUMCOUNTMAX)天然支持多阶段;不可分割的(如 STRING_AGG(DISTINCT ...) 或窗口函数嵌套)往往退回到单阶段
  • 内存与 work_mem 设置:PostgreSQL 中若 work_mem 不足,即使想单阶段也会 fallback 到两阶段磁盘哈希

如何观察实际执行路径

通过执行计划确认是否启用多阶段,重点关注节点名称与重分布操作:

  • PostgreSQL:EXPLaiN (ANALYZE, VERBOSE) 中出现 Partial Aggregate + Gather + Final Aggregate
  • ClickHouse:EXPLAIN PIPELINE 显示 AggregatingTransform 出现在多个 processor 阶段
  • Spark SQL:物理计划含 HashAggregate(partial)→ Exchange(shuffle)→ HashAggregate(final)
  • 注意 RepartitionShuffleDistribution 等关键词,它们是多阶段的明确信号
text=ZqhQzanResources