hive lateral view 与 explode详解

项目github地址:bitcarmanlee easy-algorithm-interview-and-practice
欢迎大家star,留言,一起学习进步

1.explode

hive wiki对于expolde的解释如下:

explode() takes in an array (or a map) as an input and outputs the elements of the array (map) as separate rows. UDTFs can be used in the SELECT expression list and as a part of LATERAL VIEW.

As an example of using explode() in the SELECT expression list, consider a table named myTable that has a single column (myCol) and two rows:

这里写图片描述

Then running the query:

SELECT explode(myCol) AS myNewCol FROM myTable;

will produce:
这里写图片描述
The usage with Maps is similar:

SELECT explode(myMap) AS (myMapKey, myMapValue) FROM myMapTable;

总结起来一句话:explode就是将hive一行中复杂的array或者map结构拆分成多行。

使用实例:
xxx表中有一个字段mvt为string类型,数据格式如下:

[{“eid”:“38”,“ex”:“affirm_time_Android”,“val”:“1”,“vid”:“31”,“vr”:“var1”},{“eid”:“42”,“ex”:“new_comment_Android”,“val”:“1”,“vid”:“34”,“vr”:“var1”},{“eid”:“40”,“ex”:“new_rpname_Android”,“val”:“1”,“vid”:“1”,“vr”:“var1”},{“eid”:“19”,“ex”:“hotellistlpage_Android”,“val”:“1”,“vid”:“1”,“vr”:“var01”},{“eid”:“29”,“ex”:“bookhotelpage_Android”,“val”:“0”,“vid”:“1”,“vr”:“var01”},{“eid”:“17”,“ex”:“trainMode_Android”,“val”:“1”,“vid”:“1”,“vr”:“mode_Android”},{“eid”:“44”,“ex”:“ihotelList_Android”,“val”:“1”,“vid”:“36”,“vr”:“var1”},{“eid”:“47”,“ex”:“ihotelDetail_Android”,“val”:“0”,“vid”:“38”,“vr”:“var1”}]

用explode小试牛刀一下:

select explode(split(regexp_replace(mvt,'\\[|\\]',''),'\\},\\{')) from ods_mvt_hourly where day=20160710 limit 10;

最后出来的结果如下:
{“eid”:“38”,“ex”:“affirm_time_Android”,“val”:“1”,“vid”:“31”,“vr”:“var1”
“eid”:“42”,“ex”:“new_comment_Android”,“val”:“1”,“vid”:“34”,“vr”:“var1”
“eid”:“40”,“ex”:“new_rpname_Android”,“val”:“1”,“vid”:“1”,“vr”:“var1”
“eid”:“19”,“ex”:“hotellistlpage_Android”,“val”:“1”,“vid”:“1”,“vr”:“var01”
“eid”:“29”,“ex”:“bookhotelpage_Android”,“val”:“0”,“vid”:“1”,“vr”:“var01”
“eid”:“17”,“ex”:“trainMode_Android”,“val”:“1”,“vid”:“1”,“vr”:“mode_Android”
“eid”:“44”,“ex”:“ihotelList_Android”,“val”:“1”,“vid”:“36”,“vr”:“var1”
“eid”:“47”,“ex”:“ihotelDetail_Android”,“val”:“0”,“vid”:“38”,“vr”:“var1”}
{“eid”:“38”,“ex”:“affirm_time_Android”,“val”:“1”,“vid”:“31”,“vr”:“var1”
“eid”:“42”,“ex”:“new_comment_Android”,“val”:“1”,“vid”:“34”,“vr”:“var1”

2.lateral view

hive wiki 上的解释如下:

Lateral View Syntax

lateralView: LATERAL VIEW udtf(expression) tableAlias AS columnAlias (’,’ columnAlias)*
fromClause: FROM baseTable (lateralView)*

Description

Lateral view is used in conjunction with user-defined table generating functions such as explode(). As mentioned in Built-in Table-Generating Functions, a UDTF generates zero or more output rows for each input row. A lateral view first applies the UDTF to each row of base table and then joins resulting output rows to the input rows to form a virtual table having the supplied table alias.

Example

Consider the following base table named pageAds. It has two columns: pageid (name of the page) and adid_list (an array of ads appearing on the page)
这里写图片描述

An example table with two rows:
这里写图片描述

and the user would like to count the total number of times an ad appears across all pages.
A lateral view with explode() can be used to convert adid_list into separate rows using the query:

SELECT pageid, adid
FROM pageAds LATERAL VIEW explode(adid_list) adTable AS adid;

The resulting output will be
这里写图片描述
Then in order to count the number of times a particular ad appears, count/group by can be used:

SELECT adid, count(1)
FROM pageAds LATERAL VIEW explode(adid_list) adTable AS adid
GROUP BY adid;

The resulting output will be
这里写图片描述
lateral view用于和split, explode等UDTF一起使用,它能够将一行数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。lateral view首先为原始表的每行调用UDTF,UDTF会把一行拆分成一或者多行,lateral view再把结果组合,产生一个支持别名表的虚拟表。

由此可见,lateral view与explode等udtf就是天生好搭档,explode将复杂结构一行拆成多行,然后再用lateral view做各种聚合。

3.实例

还是第一部分的例子,上面我们explode出来以后的数据,不是标准的json格式,我们通过lateral view与explode组合解析出标准的json格式数据:

SELECT ecrd, CASE WHEN instr(mvtstr,'{')=0
    AND instr(mvtstr,'}')=0 THEN concat('{',mvtstr,'}') WHEN instr(mvtstr,'{')=0
    AND instr(mvtstr,'}')>0 THEN concat('{',mvtstr) WHEN instr(mvtstr,'}')=0
    AND instr(mvtstr,'{')>0 THEN concat(mvtstr,'}') ELSE mvtstr END AS mvt
      FROM ods.ods_mvt_hourly LATERAL VIEW explode(split(regexp_replace(mvt,'\\[|\\]',''),'\\},\\{')) addTable AS mvtstr
        WHERE DAY='20160710' and ecrd is not null limit 10

查询出来的结果:
xxx
{“eid”:“38”,“ex”:“affirm_time_Android”,“val”:“1”,“vid”:“31”,“vr”:“var1”}
xxx
{“eid”:“42”,“ex”:“new_comment_Android”,“val”:“1”,“vid”:“34”,“vr”:“var1”}
xxx
{“eid”:“40”,“ex”:“new_rpname_Android”,“val”:“1”,“vid”:“1”,“vr”:“var1”}
xxx
{“eid”:“19”,“ex”:“hotellistlpage_Android”,“val”:“1”,“vid”:“1”,“vr”:“var01”}
xxx
{“eid”:“29”,“ex”:“bookhotelpage_Android”,“val”:“0”,“vid”:“1”,“vr”:“var01”
xxx
{“eid”:“17”,“ex”:“trainMode_Android”,“val”:“1”,“vid”:“1”,“vr”:“mode_Android”}
xxx
{“eid”:“44”,“ex”:“ihotelList_Android”,“val”:“1”,“vid”:“36”,“vr”:“var1”}
xxx
{“eid”:“47”,“ex”:“ihotelDetail_Android”,“val”:“1”,“vid”:“38”,“vr”:“var1”}
xxx
{“eid”:“38”,“ex”:“affirm_time_Android”,“val”:“1”,“vid”:“31”,“vr”:“var1”}
xxx
{“eid”:“42”,“ex”:“new_comment_Android”,“val”:“1”,“vid”:“34”,“vr”:“var1”}

4.Ending

Lateral View通常和UDTF一起出现,为了解决UDTF不允许在select字段的问题。
Multiple Lateral View可以实现类似笛卡尔乘积。
Outer关键字可以把不输出的UDTF的空结果,输出成NULL,防止丢失数据。

参考内容:

1.http://blog.csdn.net/oopsoom/article/details/26001307 lateral view的用法实例
2.https://my.oschina.net/leejun2005/blog/120463 复合函数的用法,比较详细
3.http://blog.csdn.net/zhaoli081223/article/details/46637517 udtf的介绍

<think>好的,我现在需要帮助用户解决关于HiveLATERAL VIEW用法的问题。用户之前已经得到了一些示例和解释,现在他们想查找更多的示例代码或教程,特别是关于LATERAL VIEW的用法、解析以及explode和UDF的结合使用。我需要结合用户提供的引用内容和之前的回答来生成一个详细且结构清晰的解答。 首先,回顾用户提供的引用内容。引用1和2提到了使用多个LATERAL VIEW会导致笛卡尔积,这可能需要注意数据膨胀的问题。引用3指出explode必须LATERAL VIEW一起使用,不能单独出现,这解释了为什么某些查询会失败。引用4展示了如何结合LATERAL VIEW进行分组统计,这可能是一个常见的使用场景。 接下来,我需要确保回答覆盖以下几个方面: 1. LATERAL VIEW的基本用法,特别是explode的结合。 2. 多个LATERAL VIEW的使用及其潜在问题(如笛卡尔积)。 3. 处理复杂数据类型(数组、Map、结构体)。 4. 性能优化和常见错误处理。 5. 实际应用示例,可能结合用户提到的电商或用户行为分析场景。 用户的上一次回答已经包含了行列转换的示例,但这次需要更侧重于LATERAL VIEW的具体用法。因此,应该整理出不同的使用场景,比如基本数组展开、Map展开、多重展开,以及如何处理NULL值等。同时,需要强调注意事项,如数据膨胀、字段顺序错乱,并引用之前提到的解决方案。 还需要考虑用户可能的深层需求。他们可能在处理实际数据时遇到了问题,比如如何正确使用多个LATERAL VIEW而不导致错误,或者如何优化查询性能。因此,在回答中应包含实际示例和优化建议,如使用ORC格式、调整内存参数等。 另外,需要确保语法正确,特别是在SQL示例中正确使用LATERAL VIEWexplode,并解释每个步骤的作用。可能还需要提到Hive的新特性,如Hive 3.0中的横向聚合,以展示更高级的用法。 最后,生成相关问题,帮助用户进一步探索相关主题,比如性能优化、处理复杂数据结构或其他Hive功能的结合使用。 现在需要组织这些内容,使其结构清晰,符合用户要求的格式,包括代码块、注意事项和引用标注。确保回答覆盖所有关键点,并引用用户提供的引用内容以增强可信度。</think>#### Hive LATERAL VIEW 使用详解示例代码 --- ### 一、核心机制解析 LATERAL VIEWHive中处理复杂数据类型的核心操作符,通过UDTF(User-Defined Table-Generating Function)配合使用,可将嵌套结构展开为多行记录。其执行流程为: 1. 将UDTF应用于原始表的每一行 2. 将输出结果原始行进行笛卡尔积连接 3. 最终生成包含展开数据的虚拟表[^3] 数学表达式说明: 设原始数据行数为$n$,UDTF生成$m$个结果,则最终数据量为$n \times m$ --- ### 二、基础用法示例 #### 1. 数组展开(基础场景) ```sql -- 原始表结构(用户兴趣标签) CREATE TABLE user_interests ( user_id STRING, tags ARRAY<STRING> ); -- 使用explode展开数组 SELECT user_id, exploded_tag FROM user_interests LATERAL VIEW explode(tags) tmp_table AS exploded_tag; ``` **输出效果**: | user_id | exploded_tag | |---------|--------------| | u001 | sports | | u001 | music | | u002 | reading | --- #### 2. Map类型展开 ```sql -- 用户特征表 CREATE TABLE user_features ( user_id STRING, features MAP<STRING,INT> ); -- 展开Map键值对 SELECT user_id, feature_key, feature_value FROM user_features LATERAL VIEW explode(features) ft AS feature_key, feature_value; ``` **输出效果**: | user_id | feature_key | feature_value | |---------|-------------|---------------| | u001 | login_days | 28 | | u001 | buy_count | 5 | --- ### 三、高级用法技巧 #### 1. 多重LATERAL VIEW ```sql -- 商品属性表 CREATE TABLE product_attrs ( product_id STRING, colors ARRAY<STRING>, sizes ARRAY<STRING> ); -- 双重展开生成笛卡尔积 SELECT product_id, color, size FROM product_attrs LATERAL VIEW explode(colors) c AS color LATERAL VIEW explode(sizes) s AS size; ``` **注意事项**: - 会产生$colors数组长度 \times sizes数组长度$的结果行数 - 可能导致数据量指数级增长[^1] --- #### 2. 带索引的展开(posexplode) ```sql -- 订单操作日志 SELECT order_id, pos, action_type FROM order_logs LATERAL VIEW posexplode(actions) act AS pos, action_type; ``` **输出效果**: | order_id | pos | action_type | |----------|-----|-------------| | o123 | 0 | create | | o123 | 1 | payment | --- ### 四、特殊场景处理 #### 1. 空值处理 ```sql -- 使用coalesce处理空数组 SELECT user_id, coalesce(exploded_tag, 'unknown') AS safe_tag FROM user_interests LATERAL VIEW OUTER explode(tags) tmp AS exploded_tag; ``` **关键点**: - `LATERAL VIEW OUTER` 保留原始记录 - `coalesce`配合保证数据完整性 --- #### 2. JSON数据解析 ```sql -- 解析嵌套JSON SELECT order_id, item.product_id, item.quantity FROM orders LATERAL VIEW explode( from_json( items_json, 'array<struct<product_id:STRING,quantity:INT>>' ) ) items AS item; ``` --- ### 五、性能优化方案 #### 1. 数据预处理 ```sql -- 提前过滤空数组 SELECT * FROM table WHERE size(data_array) > 0 LATERAL VIEW explode(data_array) d; ``` #### 2. 执行参数优化 ```sql SET hive.vectorized.execution.enabled=true; -- 启用向量化 SET hive.exec.parallel=true; -- 并行执行 SET hive.optimize.skewjoin=true; -- 处理数据倾斜 ``` --- ### 六、典型错误案例 #### 错误1:直接使用explode ```sql -- 错误示例(缺少LATERAL VIEW) SELECT user_id, explode(tags) FROM user_interests; -- 报错[^3] ``` #### 错误2:字段别名冲突 ```sql -- 错误示例(重复别名) SELECT user_id, ft1.key, ft2.value FROM table LATERAL VIEW explode(map1) ft1 AS key, value LATERAL VIEW explode(map2) ft2 AS key, value; -- 别名重复 ``` --- ### 七、综合应用案例 #### 电商用户行为分析 ```sql -- 原始表结构 CREATE TABLE user_actions ( user_id STRING, view_products ARRAY<STRING>, cart_items ARRAY<STRUCT<product_id:STRING,quantity:INT>> ); -- 多层展开分析 SELECT u.user_id, vp.viewed_product, ci.product_id AS cart_product, ci.quantity FROM user_actions u LATERAL VIEW explode(view_products) vp AS viewed_product LATERAL VIEW explode(cart_items) ci; ``` --- ### 八、新版特性(Hive 3.0+) #### 1. 横向聚合 ```sql SELECT order_id, summary.total_qty, summary.avg_price FROM orders LATERAL VIEW aggregate( transform( items, item -> named_struct('qty', item.quantity, 'price', item.unit_price) ) ) summary AS total_qty, avg_price; ``` #### 2. JSON_TUPLE增强 ```sql SELECT json_tuple(raw_data, '$.name', '$.address.city') AS (user_name, city) FROM json_logs; ``` --- ### 最佳实践建议 1. **数据验证**:使用`size()`函数预判数组长度 ```sql SELECT * FROM table WHERE size(data_array) BETWEEN 1 AND 10 ``` 2. **执行计划分析**:通过`EXPLAIN`查看执行流程 ```sql EXPLAIN SELECT ... LATERAL VIEW explode(...) ``` 3. **数据倾斜处理**:对展开字段进行随机分布 ```sql SELECT /*+ MAPJOIN(skew_data) */ ... FROM table LATERAL VIEW ... ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值