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 BY 或 SORT BY 使用。
  • 忽略 NULL 值 :当 column_name 的值为 NULL 时,该行不会被计入数组中。

3. COLLECT_LIST vs COLLECT_SET:核心区别

Hive 中有两个"收集"函数:COLLECT_LIST 和 COLLECT_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 BY 或 ORDER 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 BY 和 SORT 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 是一个功能强大但需要谨慎使用的函数。理解其特性并掌握正确的使用技巧,能帮助你更高效地完成复杂的数据聚合任务。

相关推荐
卷毛迷你猪16 小时前
快速实验篇(B07 )Session 会话化与序列
大数据·hive·hadoop
卷毛迷你猪17 小时前
快速实验篇(B08)搜索词分析实战
大数据·hive·hadoop
卷毛迷你猪1 天前
快速实验篇(B10)品类共现与关联规则实战
大数据·hive·hadoop
卷毛迷你猪1 天前
快速实验篇(B09)城市维度分析,均匀随机字段的识别与证明
大数据·hive·hadoop
卷毛迷你猪2 天前
快速实验篇(B06)页面单跳转化率
大数据·hive·hadoop
卷毛迷你猪3 天前
快速实验篇(B02)DWD 生产级升级
大数据·hive·hadoop
卷毛迷你猪3 天前
快速实验篇(B03) 用户行为漏斗与转化率
大数据·hive·hadoop
卷毛迷你猪3 天前
快速实验篇(B01)用户行为日志画像与 DWD 标准化
大数据·hive·hadoop
卷毛迷你猪3 天前
快速实验篇(B04) 热门品类 Top10 与加权排名
大数据·hive·hadoop
CarIise5 天前
Spring Boot整合MyBatis与文件上传:从分层架构到文件上传下载实战
数据仓库·hive·hadoop