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:通过先排序、后聚合的方式,用更稳定的性能表现换取系统的可靠性。

相关推荐
隔窗听雨眠8 分钟前
从取数到行动:数据分析失效的链路拆解与闭环重建
大数据·数据挖掘·数据分析
网教盟人才服务平台14 分钟前
PTP 标准化渗透能力落地,规范商用安全测试全流程
大数据·安全·web安全
金融小师妹19 分钟前
多因子定价模型:联储决议临近,黄金+1.1%的宏观驱动与走势分析
大数据·逻辑回归·线性回归
演艺大赏28 分钟前
Kyuubi + SparkSQL 查询时间戳少 8 小时解决:spark.sql.hive.convertMetastoreParquet 导致的显示偏差完整
大数据
大大大大晴天44 分钟前
Agent Loop 深度解析:理解、规划、行动、观察与纠错
大数据·agent
腾讯云大数据1 小时前
腾讯云+TBDS+智算平台:多模态数据处理与机器学习一体化实践
大数据·机器学习·云计算·腾讯云
sun153690275721 小时前
金属超声波风速风向传感器原理、RS485 Modbus-RTU 采集与气象监测站集成方案
大数据
华为LTCITR专栏流程专家许浩明1 小时前
ITR经验经典案例|服务ITR咨询|诚易达咨询公司许浩明团队辅导杰克科技服务ITR变革
大数据·人工智能·科技
涛思数据(TDengine)1 小时前
支撑药企全球化合规:TDengine 发布中美欧三地监管对照白皮书
大数据·数据库·人工智能·ai·tdengine
NineData2 小时前
NineData 社区版 V5.4.0 上线:715 条复制对比链路,AI Agent 新增表结构设计发布能力
大数据·数据库·人工智能·mysql·数据库管理工具·ninedata·数据库迁移工具