目录1. 概述2. 语法与功能3. COLLECT_LIST vs COLLECT_SET核心区别4. 实战示例5. 如何控制 COLLECT_LIST 的顺序6. 注意事项与性能优化7. 扩展用法8. 总结1. 概述COLLECT_LIST是 Hive 中一个非常实用的聚合函数它能够将分组内某列的所有值“收集”起来打包成一个数组ARRAY类型返回。它就像是给数据拍了一张“集体照”把同一组里的所有成员都放进了同一张图片里。它是 Hive 实现“行转列”功能的核心函数常与GROUP BY语句配合使用将原本多行的数据压缩到一行的一个字段中。2. 语法与功能COLLECT_LIST的语法非常简洁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_LISTCOLLECT_SET处理重复值保留所有值包括重复自动去重仅保留唯一值结果顺序相对有序基本按输入顺序排列无序结果的顺序不确定返回类型ARRAYARRAY使用场景需要保留所有明细记录的场景如用户的所有订单历史需要统计不重复项的场景如用户购买过的商品品类一句话总结当需要保留所有值包括重复值时用COLLECT_LIST当需要去除重复值获得唯一列表时用COLLECT_SET。4. 实战示例假设我们有一张记录了用户观看视频历史的表user_video_loguser_idvideo_namewatch_date101Hive Tutorial2024-01-01101Spark Guide2024-01-02101Hive Tutorial2024-01-03102Kafka 1012024-01-01102Kafka 1012024-01-05场景一统计每个用户看过的所有视频保留重复-- 使用 COLLECT_LIST将保留用户101观看的两次 Hive TutorialSELECTuser_id,COLLECT_LIST(video_name)ASall_videosFROMuser_video_logGROUPBYuser_id;查询结果user_idall_videos101[Hive Tutorial, Spark Guide, Hive Tutorial]102[Kafka 101, Kafka 101]场景二统计每个用户看过哪些不同的视频去重-- 使用 COLLECT_SET将自动去除 Hive Tutorial 的重复SELECTuser_id,COLLECT_SET(video_name)ASunique_videosFROMuser_video_logGROUPBYuser_id;查询结果user_idunique_videos101[Hive Tutorial, Spark Guide]102[Kafka 101]5. 如何控制 COLLECT_LIST 的顺序在实际业务中我们常常需要按某个特定顺序如时间顺序来排列聚合后的数组。由于COLLECT_LIST的顺序在分布式环境中可能不稳定因此需要主动控制。方法一子查询中使用SORT BY或ORDER BY推荐SELECTuser_id,COLLECT_LIST(video_name)ASordered_videos,COLLECT_LIST(watch_date)ASordered_datesFROM(SELECTuser_id,video_name,watch_dateFROMuser_video_log DISTRIBUTEBYuser_id-- 确保同一 user_id 的数据被分到同一个 reducer 进行处理SORTBYuser_id,watch_dateASC-- 在该 reducer 内按 watch_date 升序排序)tGROUPBYuser_id;核心技巧在内层子查询中使用DISTRIBUTE BY和SORT BY来控制数据进入COLLECT_LIST前的顺序。DISTRIBUTE BY确保了相同user_id的数据被发送到同一个ReducerSORT BY则在该Reducer内部对数据进行排序从而保证了聚合后的数组顺序正确。方法二使用SORT_ARRAY函数SELECTuser_id,SORT_ARRAY(COLLECT_LIST(video_name))ASsorted_videosFROMuser_video_logGROUPBYuser_id;SORT_ARRAY可以对数组进行全局的升序排序。这是一种更简洁的方法但它的灵活性有限只能对整个数组进行升序排序无法实现复杂或自定义的排序逻辑。6. 注意事项与性能优化内存与性能风险COLLECT_LIST会将分组内所有数据加载到内存中。如果某个分组的数据量巨大例如为“用户ID”为空的数百万条记录极易导致OOM内存溢出错误。建议在处理前先过滤掉这些异常数据或通过子查询限制数据量。数据倾斜风险当某些分组Key的数据量远超其他分组时会导致负责处理该分组的 Reducer 任务成为整个作业的瓶颈即数据倾斜。使用LIMIT控制大小如果业务允许可以使用LIMIT子句来限制COLLECT_LIST收集的数据量防止内存溢出。7. 扩展用法1. 行转列并拼接为字符串这是COLLECT_LIST最经典的用法。将收集到的数组通过CONCAT_WS函数用指定的分隔符拼接成一个字符串。SELECTuser_id,CONCAT_WS(,,COLLECT_LIST(video_name))ASvideo_list_strFROMuser_video_logGROUPBYuser_id;2. 用SIZE函数统计数量SIZE函数可以返回数组的长度即分组内元素的数量。SELECTuser_id,SIZE(COLLECT_LIST(video_name))ASwatch_countFROMuser_video_logGROUPBYuser_id;8. 总结维度核心内容核心功能将分组内一列的多行值聚合为一个数组实现“行转列”。与COLLECT_SET的区别COLLECT_LIST保留重复值COLLECT_SET自动去重。顺序控制使用DISTRIBUTE BYSORT BY精确控制或使用SORT_ARRAY进行全局升序排序。性能与风险需警惕内存溢出和数据倾斜风险建议过滤数据、控制数据量或增加内存。扩展用法常与CONCAT_WS拼接为字符串或与SIZE函数统计数量。COLLECT_LIST是一个功能强大但需要谨慎使用的函数。理解其特性并掌握正确的使用技巧能帮助你更高效地完成复杂的数据聚合任务。