Spark SQL 聚合函数:collect_list 与 collect_set 用法详解
Spark SQL 聚合函数:collect_list 与 collect_set 用法详解
官网:
https://spark.apache.org/docs/latest/api/sql/index.html#collect_list
1. 函数简介
collect_list(expr)
- 功能:收集并返回一个包含所有元素(允许重复)的列表。
- 特点:
- 不去重
- 保持输入顺序(如果输入顺序确定)
- 非确定性(因为输出顺序依赖于输入行的顺序,而这个顺序可能是非确定性的)
collect_set(expr)
- 功能:收集并返回一个包含唯一元素的集合(自动去重)。
- 特点:
- 自动去重
- 不保证输出顺序(因为是集合)
- 非确定性(因为输出顺序依赖于输入行的顺序)
Tips:
- 内存消耗:当处理大数据集时,这两个函数都可能导致内存问题,特别是
collect_list
因为它不进行去重操作。 - 非确定性:由于这些函数依赖于输入行的顺序,而这个顺序可能因执行计划的不同而变化,因此结果集的顺序也可能不同。
collect_list 的结果依赖数据的物理顺序,特别是在分布式环境中,顺序是不确定的。
如果希望结果有序,可以使用 sort_array 显式排序。
https://spark.apache.org/docs/latest/api/sql/index.html#sort_array
SELECTs.name,sort_array(collect_list(g.score), false) AS sorted_scores
FROM students s
JOIN grades g ON s.student_id = g.student_id
GROUP BY s.name;
Demo:
1: 使用 collect_list
收集每个角色的所有技能(包括重复)
WITH warriors_skills AS (SELECT '悟空' AS warrior, '龟派气功' AS skill UNION ALLSELECT '悟空', '瞬间移动' UNION ALLSELECT '悟空', '龟派气功' UNION ALLSELECT '贝吉塔', '毁灭闪光' UNION ALLSELECT '贝吉塔', '最终闪光' UNION ALLSELECT '比克', '魔贯光杀炮'
)SELECT warrior, collect_list(skill) AS all_skills
FROM warriors_skills
GROUP BY warrior;
+---------+----------------------------------+
| warrior | all_skills |
+---------+----------------------------------+
| 悟空 | ["龟派气功", "瞬间移动", "龟派气功"]|
| 贝吉塔 | ["毁灭闪光", "最终闪光"] |
| 比克 | ["魔贯光杀炮"] |
+---------+----------------------------------+
collect_list
函数保留了所有的技能名称,包括重复的“龟派气功”。
2: 使用 collect_set
收集每个角色的独特技能(去重)
如果我们只关心每个角色使用过的独特技能,可以使用 collect_set
函数:
WITH warriors_skills AS (SELECT '悟空' AS warrior, '龟派气功' AS skill UNION ALLSELECT '悟空', '瞬间移动' UNION ALLSELECT '悟空', '龟派气功' UNION ALLSELECT '贝吉塔', '毁灭闪光' UNION ALLSELECT '贝吉塔', '最终闪光' UNION ALLSELECT '比克', '魔贯光杀炮'
)SELECT warrior, collect_set(skill) AS unique_skills
FROM warriors_skills
GROUP BY warrior;
+---------+--------------------------+
| warrior | unique_skills |
+---------+--------------------------+
| 悟空 | ["龟派气功", "瞬间移动"] |
| 贝吉塔 | ["毁灭闪光", "最终闪光"] |
| 比克 | ["魔贯光杀炮"] |
+---------+--------------------------+
collect_set
自动去除了重复的技能名称,确保每个技能仅出现一次。