COLLECT_LIST函数详解

📑 目录

  • [1. 概述](#1. 概述)
  • [2. 语法与功能](#2. 语法与功能)
  • [3. COLLECT_LIST vs COLLECT_SET:核心区别](#3. COLLECT_LIST vs COLLECT_SET:核心区别)
  • [4. 实战示例](#4. 实战示例)
  • [5. 如何控制 COLLECT_LIST 的顺序](#5. 如何控制 COLLECT_LIST 的顺序)
  • [6. 注意事项与性能优化](#6. 注意事项与性能优化)
  • [7. 扩展用法](#7. 扩展用法)
  • [8. 总结](#8. 总结)

1. 概述

COLLECT_LIST 是 Hive 中一个非常实用的聚合函数,它能够将分组内某列的所有值"收集"起来,打包成一个数组(ARRAY 类型)返回。它就像是给数据拍了一张"集体照",把同一组里的所有成员都放进了同一张图片里。

它是 Hive 实现"行转列"功能的核心函数,常与 GROUP BY 语句配合使用,将原本多行的数据压缩到一行的一个字段中。


2. 语法与功能

COLLECT_LIST 的语法非常简洁:

sql 复制代码
COLLECT_LIST( [DISTINCT] column_name )  -- Hive 3.0 之后支持 DISTINCT 关键字,但更推荐使用 COLLECT_SET

该函数接受一个列名作为参数,将其所有值(包括重复值)放入一个列表(数组)中。

功能特点:

  • 保留重复值 :与它的"兄弟"函数 COLLECT_SET 不同,COLLECT_LIST 会忠实地保留分组内所有的数据,即使它们是完全重复的。
  • 保留输入顺序 :通常情况下,结果数组中的元素顺序与原始数据输入的顺序一致。但此顺序在执行大规模分布式任务时可能不稳定,因此在实际应用中,如果需要保证顺序,建议结合 ORDER BYSORT BY 使用。
  • 忽略 NULL 值 :当 column_name 的值为 NULL 时,该行不会被计入数组中。

3. COLLECT_LIST vs COLLECT_SET:核心区别

Hive 中有两个"收集"函数:COLLECT_LISTCOLLECT_SET。它们的主要区别在于是否对结果去重

特性 COLLECT_LIST COLLECT_SET
处理重复值 保留所有值(包括重复) 自动去重,仅保留唯一值
结果顺序 相对有序,基本按输入顺序排列 无序,结果的顺序不确定
返回类型 ARRAY ARRAY
使用场景 需要保留所有明细记录的场景,如用户的所有订单历史 需要统计不重复项的场景,如用户购买过的商品品类

一句话总结 :当需要保留所有值,包括重复值时,用 COLLECT_LIST;当需要去除重复值,获得唯一列表时,用 COLLECT_SET


4. 实战示例

假设我们有一张记录了用户观看视频历史的表 user_video_log

user_id video_name watch_date
101 "Hive Tutorial" 2024-01-01
101 "Spark Guide" 2024-01-02
101 "Hive Tutorial" 2024-01-03
102 "Kafka 101" 2024-01-01
102 "Kafka 101" 2024-01-05

场景一:统计每个用户看过的所有视频(保留重复)

sql 复制代码
-- 使用 COLLECT_LIST,将保留用户101观看的两次 'Hive Tutorial'
SELECT
    user_id,
    COLLECT_LIST(video_name) AS all_videos
FROM user_video_log
GROUP BY user_id;

查询结果:

user_id all_videos
101 ["Hive Tutorial", "Spark Guide", "Hive Tutorial"]
102 ["Kafka 101", "Kafka 101"]

场景二:统计每个用户看过哪些不同的视频(去重)

sql 复制代码
-- 使用 COLLECT_SET,将自动去除 'Hive Tutorial' 的重复
SELECT
    user_id,
    COLLECT_SET(video_name) AS unique_videos
FROM user_video_log
GROUP BY user_id;

查询结果:

user_id unique_videos
101 ["Hive Tutorial", "Spark Guide"]
102 ["Kafka 101"]

5. 如何控制 COLLECT_LIST 的顺序

在实际业务中,我们常常需要按某个特定顺序(如时间顺序)来排列聚合后的数组。由于 COLLECT_LIST 的顺序在分布式环境中可能不稳定,因此需要主动控制。

方法一:子查询中使用 SORT BYORDER BY(推荐)

sql 复制代码
SELECT
    user_id,
    COLLECT_LIST(video_name) AS ordered_videos,
    COLLECT_LIST(watch_date) AS ordered_dates
FROM (
    SELECT user_id, video_name, watch_date
    FROM user_video_log
    DISTRIBUTE BY user_id        -- 确保同一 user_id 的数据被分到同一个 reducer 进行处理
    SORT BY user_id, watch_date ASC  -- 在该 reducer 内按 watch_date 升序排序
) t
GROUP BY user_id;

核心技巧 :在内层子查询中,使用 DISTRIBUTE BYSORT BY 来控制数据进入 COLLECT_LIST 前的顺序。DISTRIBUTE BY 确保了相同 user_id 的数据被发送到同一个Reducer,SORT BY 则在该Reducer内部对数据进行排序,从而保证了聚合后的数组顺序正确。

方法二:使用 SORT_ARRAY 函数

sql 复制代码
SELECT
    user_id,
    SORT_ARRAY(COLLECT_LIST(video_name)) AS sorted_videos
FROM user_video_log
GROUP BY user_id;

SORT_ARRAY 可以对数组进行全局的升序排序。这是一种更简洁的方法,但它的灵活性有限,只能对整个数组进行升序排序,无法实现复杂或自定义的排序逻辑。


6. 注意事项与性能优化

  • 内存与性能风险COLLECT_LIST 会将分组内所有数据加载到内存中。如果某个分组的数据量巨大(例如为"用户ID"为空的数百万条记录),极易导致 OOM(内存溢出) 错误。建议在处理前先过滤掉这些异常数据或通过子查询限制数据量。

  • 数据倾斜风险:当某些分组(Key)的数据量远超其他分组时,会导致负责处理该分组的 Reducer 任务成为整个作业的瓶颈,即数据倾斜。

  • 使用 LIMIT 控制大小 :如果业务允许,可以使用 LIMIT 子句来限制 COLLECT_LIST 收集的数据量,防止内存溢出。


7. 扩展用法

1. 行转列并拼接为字符串

这是 COLLECT_LIST 最经典的用法。将收集到的数组通过 CONCAT_WS 函数,用指定的分隔符拼接成一个字符串。

sql 复制代码
SELECT
    user_id,
    CONCAT_WS(',', COLLECT_LIST(video_name)) AS video_list_str
FROM user_video_log
GROUP BY user_id;

2. 用 SIZE 函数统计数量

SIZE 函数可以返回数组的长度,即分组内元素的数量。

sql 复制代码
SELECT
    user_id,
    SIZE(COLLECT_LIST(video_name)) AS watch_count
FROM user_video_log
GROUP BY user_id;

8. 总结

维度 核心内容
核心功能 将分组内一列的多行值,聚合为一个数组,实现"行转列"。
COLLECT_SET 的区别 COLLECT_LIST 保留重复值COLLECT_SET 自动去重
顺序控制 使用 DISTRIBUTE BY + SORT BY 精确控制;或使用 SORT_ARRAY 进行全局升序排序。
性能与风险 需警惕内存溢出数据倾斜 风险;建议过滤数据控制数据量增加内存
扩展用法 常与 CONCAT_WS 拼接为字符串,或与 SIZE 函数统计数量。

COLLECT_LIST 是一个功能强大但需要谨慎使用的函数。理解其特性并掌握正确的使用技巧,能帮助你更高效地完成复杂的数据聚合任务。

相关推荐
隐于花海,等待花开3 小时前
数据开发常问的技术性问题及解答
大数据·hive
隐于花海,等待花开10 小时前
窗口函数之排序函数详细解读及示例
大数据·数据库·hive
隐于花海,等待花开11 小时前
Hive 正则函数详解与示例
数据仓库·hive·hadoop
隐于花海,等待花开11 小时前
Hive专题:数据开发面试高频题(TopN、留存、连续登录等)
hive·hadoop·面试
Hadoop_Liang1 天前
Hive的ORDER BY、SORT BY、DISTRIBUTE BY、CLUSTER BY对比及案例实践
数据仓库·hive·hadoop
杭州杭州杭州2 天前
数仓实验1
hive
杭州杭州杭州2 天前
数仓实验2
hive
杭州杭州杭州2 天前
数仓实验3
hive
隐于花海,等待花开3 天前
HIVE日期函数大全
数据仓库·hive·hadoop