Spark聚合算法:HashAggregate与SortAggregate详解

为了让你一眼看透本质,我们把 Spark 聚合 比作"分拣扑克牌":

  • HashAggregate = 按点数直接扔进对应的桶(内存中建哈希表)。

  • SortAggregate = 先把牌排好序,再从头数(排序后顺序扫描)。

假设我们有一堆杂乱的扑克牌(数据),要统计 每种花色(Suit)的张数GROUP BY suit)。

原始数据(乱序):

♥️3, ♠️K, ♦️5, ♥️7, ♠️A, ♦️2, ♣️4, ♣️Q


玩法一:HashAggregate(哈希聚合)------ "按花色扔桶"

操作步骤

  1. Spark 在内存中建一个"哈希桶"(HashMap),每个花色对应一个格子。

  2. 每来一张牌,直接计算花色 Hash 值,找到对应的格子:

    • 看到 ♥️3 → 找到"红桃"格,计数 1。

    • 看到 ♠️K → 找到"黑桃"格,计数 1。

    • 看到 ♦️5 → 找到"方块"格,计数 1。

    • 看到 ♥️7 → 找到"红桃"格,计数变成 2(原地更新)。

  3. 所有牌读完,直接统计每个格子里的总数。

维度 特点
优点 速度极快,数据来一条处理一条,无需等待其他数据。
缺点 吃内存。如果花色(分组 Key)有上亿种,哈希表会撑爆内存,导致 OOM 或频繁溢写磁盘。
适用场景 数据分组后 Key 的种类相对较少,内存装得下。

玩法二:SortAggregate(排序聚合)------ "排队后顺序数"

操作步骤

1. 先全局/分区排序:不管牌原来在哪,先把所有扑克牌按"花色"排好队(Shuffle + Sort)。排完后顺序为:

♣️4, ♣️Q, ♦️2, ♦️5, ♥️3, ♥️7, ♠️A, ♠️K

2. 再顺序扫描:从头到尾扫一遍,因为同花色都挤在一起了,所以只需要记住"当前花色":

  • 扫到 ♣️4(当前为梅花),累加;扫到 ♣️Q(还是梅花),累加;遇到 ♦️2(花色变了),立刻把梅花的统计结果输出,然后开始数方块。
  1. 扫完整个队列,所有统计结果就出来了。
维度 特点
优点 内存占用小。排序时可以借助磁盘(外部排序),不需要在内存中维持巨大的哈希表。
缺点 速度较慢。必须等所有数据排好序才能开始聚合,且排序本身消耗大量的 CPU 和 Shuffle 网络开销。
适用场景 数据量极大,Key 种类极多,内存不够装下哈希表时,作为"兜底策略"使用。

两者终极对决(一图看懂)

对比维度 HashAggregate SortAggregate
核心操作 哈希查找 + 内存更新 全局排序 + 顺序遍历
对数据要求 不需要数据有序 必须先按 Key 排好序
内存风险 高(Key 太多会撑爆) 低(依赖磁盘缓冲)
执行效率 快(O(1) 查找) 慢(O(n log n) 排序)
Spark 优先度 默认首选(高性能) 当 HashAgg 内存不足时回退使用

Spark 实际执行中的"骚操作"(必看)

在实际的物理执行计划中,Spark 为了兼顾速度和稳定性,常采用两阶段聚合

  1. 部分聚合(Partial HashAggregate)

    在每个数据分片(Task)内部,先用 HashAggregate 快速合并局部数据(比如每个 Task 内先数一遍自己手上的牌),大幅减少 Shuffle 的数据量。

  2. 最终聚合(Final 阶段)

    Shuffle 后,如果 Key 的数量依然巨大,Spark 可能会放弃 HashAggregate,改用 SortAggregate 来完成最后的全局合并,防止内存爆炸。

在 Spark SQL 中,HashAggregate 是默认首选,SortAggregate 则作为"替补" ,在 HashAggregate 无法胜任或效率不佳时登场。

简单来说,HashAggregate 追求极致速度,而 SortAggregate 保证系统稳定。


🚀 HashAggregate:高性能的默认选项

只要条件允许,Spark SQL 会优先选择 HashAggregate 来追求最佳性能。它通常出现在这些场景:

  • 标准 GROUP BY 聚合 :这是最典型的场景,例如 SELECT category, SUM(sales) FROM table GROUP BY category

  • DISTINCT 去重聚合 :执行 SELECT COUNT(DISTINCT col) FROM table 这类操作时,Spark 会使用 HashAggregate 分阶段去重。

  • 无 GROUP BY 的全局聚合 :即使是计算整个表的 SELECT COUNT(*) FROM table,也会使用 HashAggregate 进行全局聚合。

值得注意的是,HashAggregate 通常以"成对"方式出现:先在每个分区内进行局部聚合 (Partial),经过 Exchange 节点完成数据 shufflle 后,再进行全局聚合(Final)。

🛡️ SortAggregate:保障稳定的后备方案

当出现以下情况时,Spark SQL 会放弃 HashAggregate,转而使用更稳定的 SortAggregate

  • 内存压力过大 :当分组键(Key)过多,导致 HashAggregate 使用的哈希表大到无法放入内存时,Spark 会"回退"到 SortAggregate 以避免内存溢出(OOM)。

  • 数据类型不匹配(核心原因)HashAggregate 要求聚合函数中使用的数据类型是"可变"的。当你使用 first()last() 或某些自定义聚合函数(UDAF) 时,会因数据类型限制而强制使用 SortAggregate

  • 数据已预先排序 :如果数据流本身已经按分组键排好序,那么使用 SortAggregate 可以省去额外的排序开销,速度可能更快。

💎 总结

Spark SQL 选择聚合策略的逻辑是:

  1. 首选 HashAggregate :利用哈希表进行 O(1) 查找,实现高性能聚合。

  2. 条件不满足时,降级为 SortAggregate:通过先排序、后聚合的方式,用更稳定的性能表现换取系统的可靠性。

相关推荐
维双云10 小时前
2026小程序自助搭建平台有哪些?零基础易上手工具与使用场景整理
大数据
cetcht888810 小时前
深耕配电智能化升级 多场景项目落地筑牢电力运维安全防线
大数据·数据库·人工智能
挨踢诗人12 小时前
金蝶K3 WISE × 乐企平台 直连数电票集成解决方案(商贸企业开票自动化)
大数据·运维·自动化
Elastic 中国社区官方博客18 小时前
搜索倍增器:推动收入、生产力和 AI 实现规模化
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
wjkjpcba18 小时前
机器人控制板PCBA怎么加工?从SMT贴片到BGA焊接解析机器人电子制造工艺
大数据·人工智能
Capricorn198820 小时前
解决全网抄 Karpathy 导致的 LLM Wiki 污染?基于知芽 Notebook Skill 的 raw/ 笔记法排障指南
大数据·论文阅读·人工智能·笔记·论文笔记
临沂GEO20 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
人民新视野21 小时前
党建引领促交流 互学互鉴共提升 —— 赴启信创格(北京)营销科技有限公司交流学习活动总结
大数据·人工智能·科技
中科高级技工学校1 天前
乌鲁木齐中医康复学习经历分享
大数据·学习