目录1. 概述2. 语法详解2.1 LATERAL VIEW 基础语法2.2 EXPLODE 函数语法2.3 组合语法LATERAL VIEW EXPLODE3. 核心功能与原理4. 实战示例4.1 将 ARRAY 列展开为多行4.2 将 MAP 列展开为多行key, value4.3 将逗号分隔的字符串展开为多行SPLIT EXPLODE4.4 使用 LATERAL VIEW OUTER 保留空数组/NULL 行4.5 多个 LATERAL VIEW 的笛卡尔积效果5. 注意事项与常见陷阱5.1 空值NULL与空数组的处理5.2 性能影响数据膨胀5.3 单个 SELECT 中多个 UDTF 的限制5.4 列名冲突与别名规范6. 高级用法6.1 POSEXPLODE带下标的展开6.2 多个 EXPLODE 按位置对齐使用 POSEXPLODE JOIN6.3 嵌套 LATERAL VIEW 处理数组中的结构体7. 总结1. 概述在 Hive 中LATERAL VIEW与EXPLODE是一对黄金搭档用于将一行数据中的复杂类型数组或 Map拆分成多行同时保留原始行的其他列。这通常被称为“列转行”或“数据扁平化”。EXPLODE是一个表生成函数UDTF它接收一个数组或 Map为每个元素输出一行。LATERAL VIEW是一个特殊的语法它将 UDTF 生成的虚拟表与原始表的每一行进行横向连接从而允许我们在同一查询中同时访问原始列和爆炸后的元素。没有LATERAL VIEW时EXPLODE不能与其他列一起使用老版本限制。LATERAL VIEW解决了这个问题是处理嵌套数据的核心工具。2. 语法详解2.1 LATERAL VIEW 基础语法LATERALVIEW[OUTER]udtf_function(expression)table_aliasAScolumn_alias[,column_alias,...]OUTER可选关键字。当 UDTF 返回空结果时仍然为原始行生成一行其他列为 NULL类似于LEFT JOIN。udtf_function表生成函数如EXPLODE、POSEXPLODE、STACK等。table_alias虚拟表的别名可省略但推荐写。column_aliasUDTF 输出列的别名数量需与 UDTF 的输出列数匹配。2.2 EXPLODE 函数语法-- 处理 ARRAY 类型输出单列EXPLODE(ARRAYTa)-- 默认输出列名为 col-- 处理 MAP 类型输出两列 (key, value)EXPLODE(MAPK,Vm)-- 默认输出列名为 key, value2.3 组合语法LATERAL VIEW EXPLODESELECToriginal_column,exploded_columnFROMoriginal_table LATERALVIEWEXPLODE(array_column)aliasASexploded_column;示例SELECTuser_id,tagFROMuser_tags LATERALVIEWEXPLODE(tags_array)tAStag;3. 核心功能与原理LATERAL VIEW EXPLODE的核心功能是将一行变多行读取原始表的一行数据。对该行的指定数组或 Map列调用EXPLODE生成多行每行一个元素。将原始行的其他列与每一行爆炸结果进行横向连接形成一个新的结果行。对所有原始行重复上述过程最终输出一个“扁平化”的表。这种操作非常适合处理用户标签一行多个标签 → 每个标签一行订单商品列表一行多个商品 → 每个商品一行日志中的参数数组JSON 解析后的嵌套数组4. 实战示例4.1 将 ARRAY 列展开为多行原始表user_hobbiesuser_idhobbies_array1[“reading”,“swimming”]2[“coding”,“gaming”]SQLSELECTuser_id,hobbyFROMuser_hobbies LATERALVIEWEXPLODE(hobbies_array)tAShobby;结果user_idhobby1reading1swimming2coding2gaming4.2 将 MAP 列展开为多行key, value原始表user_propsuser_idprops_map1{“city”:“Beijing”,“job”:“engineer”}2{“city”:“Shanghai”,“job”:“designer”}SQLSELECTuser_id,prop_key,prop_valueFROMuser_props LATERALVIEWEXPLODE(props_map)tASprop_key,prop_value;结果user_idprop_keyprop_value1cityBeijing1jobengineer2cityShanghai2jobdesigner4.3 将逗号分隔的字符串展开为多行SPLIT EXPLODE原始表user_hobby_struser_idhobby_str1“reading,swimming”2“coding,gaming”SQLSELECTuser_id,hobbyFROMuser_hobby_str LATERALVIEWEXPLODE(SPLIT(hobby_str,,))tAShobby;结果同上。SPLIT将字符串转为数组再交给EXPLODE展开。4.4 使用 LATERAL VIEW OUTER 保留空数组/NULL 行当数组列为空或 NULL 时默认的LATERAL VIEW会丢弃该原始行。若想保留这些行爆炸列为 NULL需使用OUTER。原始表user_idtags_array1[“hive”]2[]3NULL普通 LATERAL VIEWSELECTuser_id,tagFROMuser_tags LATERALVIEWEXPLODE(tags_array)tAStag;结果只有 user_id1 的一行2 和 3 丢失。使用 OUTERSELECTuser_id,tagFROMuser_tags LATERALVIEWOUTEREXPLODE(tags_array)tAStag;结果user_idtag1hive2NULL3NULL4.5 多个 LATERAL VIEW 的笛卡尔积效果对同一行应用两个EXPLODE会生成两个数组元素的笛卡尔积交叉连接。原始表user_idarr1arr21[“a”,“b”][1,2]SQLSELECTuser_id,e1,e2FROMmy_table LATERALVIEWEXPLODE(arr1)t1ASe1 LATERALVIEWEXPLODE(arr2)t2ASe2;结果4 行(a,1), (a,2), (b,1), (b,2)。注意这种行为可能导致数据膨胀需要谨慎。5. 注意事项与常见陷阱5.1 空值NULL与空数组的处理如果EXPLODE的输入为NULL或空数组[]默认情况下该原始行不会产生任何输出行。如果需要保留原始行必须使用LATERAL VIEW OUTER。对于 Map 类型同样适用。5.2 性能影响数据膨胀EXPLODE会显著增加行数。假设一个表有 1 亿行每行数组平均长度 100展开后变为 100 亿行可能导致存储和计算资源急剧消耗。Shuffle 和 Join 阶段压力巨大。查询变慢甚至 OOM。优化建议尽量在爆炸前通过 WHERE 条件过滤掉不需要的原始行。避免对超大数组使用EXPLODE后再做JOIN或GROUP BY。考虑使用COLLECT_LIST的反向聚合来减少行数。5.3 单个 SELECT 中多个 UDTF 的限制在老版本 Hive0.12中一个 SELECT 子句只能包含一个 UDTF。现代版本通过LATERAL VIEW解决了此问题但仍不允许直接写SELECT EXPLODE(arr1), EXPLODE(arr2)。必须写两个LATERAL VIEW。5.4 列名冲突与别名规范每个LATERAL VIEW必须指定虚拟表别名和列别名。多个LATERAL VIEW的列别名不能重复。如果不指定列别名默认列名为col对于 ARRAY或key/value对于 MAP。建议总是显式命名避免歧义。6. 高级用法6.1 POSEXPLODE带下标的展开POSEXPLODE不仅返回数组元素还返回元素的位置索引从 0 开始。SELECTuser_id,pos,tagFROMuser_tags LATERALVIEWPOSEXPLODE(tags_array)tASpos,tag;结果假设tags_array [hive,spark]user_idpostag10hive11spark6.2 多个 EXPLODE 按位置对齐使用 POSEXPLODE JOIN当需要将两个数组按相同位置对应展开而非笛卡尔积时可以用POSEXPLODE分别获取下标再通过下标 JOIN。原始表user_arrays(user_id, arr_a, arr_b)要求将arr_a和arr_b相同位置的元素配对输出。SQLSELECTt1.user_id,t1.pos,t1.a,t2.bFROM(SELECTuser_id,pos,aFROMuser_arrays LATERALVIEWPOSEXPLODE(arr_a)tASpos,a)t1JOIN(SELECTuser_id,pos,bFROMuser_arrays LATERALVIEWPOSEXPLODE(arr_b)tASpos,b)t2ONt1.user_idt2.user_idANDt1.post2.pos;这样避免了笛卡尔积性能更好且语义正确。6.3 嵌套 LATERAL VIEW 处理数组中的结构体如果数组元素是结构体STRUCT可以先用EXPLODE展开再通过点语法访问结构体字段。原始表ordersorder_iditems ARRAYSTRUCTproduct_id:INT, quantity:INTSQLSELECTorder_id,item.product_id,item.quantityFROMorders LATERALVIEWEXPLODE(items)tASitem;7. 总结维度核心内容函数角色LATERAL VIEW连接 UDTF 与原始行EXPLODE将数组/Map 展开为多行典型场景标签拆解、订单商品明细、JSON 数组扁平化、日志参数展开保留原始行使用LATERAL VIEW OUTER避免空数组/NULL 行丢失性能风险数据膨胀谨慎处理大数组避免展开后立即 JOIN 或聚合多数组对齐使用POSEXPLODE 下标 JOIN而非多个EXPLODE的笛卡尔积语法关键必须为虚拟表和输出列指定别名多个LATERAL VIEW按顺序执行一句话记忆LATERAL VIEW EXPLODE将“数组行”拆成“元素行”是数据扁平化的万能钥匙别忘了OUTER保行POSEXPLODE保序。