Spark INLINE和LATERAL VIEW EXPLODE有什么区别?

7
在Spark中,对于以下用例,我想了解使用INLINEEXPLODE的主要区别是什么... 我不确定是否有任何性能影响,或者是否更喜欢一种方法,或者在哪些其他用例中适用其中一种而不适用另一种...
用例是从一个复杂数据类型(结构数组)中选择2个字段,我的直觉是使用INLINE,因为它会展开结构数组。
例如:
WITH sample AS (
 SELECT 1 AS id,
        array(NAMED_STRUCT('name', 'frank',
                           'age', 40,
                           'state', 'Texas'
                           ),
              NAMED_STRUCT('name', 'maria',
                           'age', 51,
                           'state', 'Georgia'
                           )
              )            
            AS array_of_structs
),

inline_data AS (
SELECT id,
        INLINE(array_of_structs)
FROM sample
)

SELECT id,
        name AS person_name,
        age AS person_age
FROM inline_data

使用 LATERAL VIEW EXPLODE:

WITH sample AS (
 SELECT 1 AS id,
        array(NAMED_STRUCT('name', 'frank',
                           'age', 40,
                           'state', 'Texas'
                           ),
              NAMED_STRUCT('name', 'maria',
                           'age', 51,
                           'state', 'Georgia'
                           )
              )            
            AS array_of_structs
)

SELECT  id,
        person.name,
        person.age
FROM sample
LATERAL VIEW EXPLODE(array_of_structs) exploded_people as person 

文档清楚地说明了它们的用途,但我希望更好地了解何时选择其中一个而不是另一个。
1个回答

10
< p >EXPLODE UDTF 会生成结构体行(类型为结构体的单列),要获取人名,需要使用 person.name

WITH sample AS (
 SELECT 1 AS id,
        array(NAMED_STRUCT('name', 'frank',
                           'age', 40,
                           'state', 'Texas'
                           ),
              NAMED_STRUCT('name', 'maria',
                           'age', 51,
                           'state', 'Georgia'
                           )
              )            
            AS array_of_structs
)

SELECT  id,
        person.name,
        person.age
FROM sample
LATERAL VIEW explode(array_of_structs) exploded_people as person

结果:

id,name,age
1,frank,40
1,maria,51
INLINE UDTF会生成一个包含N列的行集(N = 结构中顶级元素的数量),因此您不需要使用点符号person.name ,因为name 和其他结构元素已经被INLINE提取出来。
WITH sample AS (
 SELECT 1 AS id,
        array(NAMED_STRUCT('name', 'frank',
                           'age', 40,
                           'state', 'Texas'
                           ),
              NAMED_STRUCT('name', 'maria',
                           'age', 51,
                           'state', 'Georgia'
                           )
              )            
            AS array_of_structs
)

SELECT  id,
        name,
        age
FROM sample
LATERAL VIEW inline(array_of_structs) exploded_people as name, age, state

结果:

id,name,age
1,frank,40
1,maria,51 

INLINEEXPLODE 都是UDTF,在Hive中需要使用LATERAL VIEW,在Spark中不需要。唯一的区别是 EXPLODE 返回数组元素数据集(在您的情况下是 struct),而 INLINE 用于获取已提取的结构元素。对于 INLINE,您需要像这样定义所有 struct 元素:LATERAL VIEW inline(array_of_structs) exploded_people as name,age,state

从性能角度来看,INLINE 和 EXPLODE 的工作方式相同,可以使用 EXPLAIN 命令检查计划。在 UDTF 中或 UDTF 之后提取结构元素不会影响性能。

INLINE 在 Hive 中需要描述所有 struct 元素,而 EXPLODE 不需要,因此如果您不需要提取所有 struct 元素或根本不需要提取元素,则 EXPLODE 可能更方便。当您需要提取所有或大部分结构元素时,INLINE 是方便的。

您的第一个代码示例仅在 Spark 中起作用。在 Hive 2.1.1 中,它会抛出异常,因为需要使用 lateral view

在 Spark 中,这也可以工作:

inline_data AS (
SELECT id,
        EXPLODE(array_of_structs) as person
FROM sample
)

要获取年龄列,您需要使用person.age


谢谢您的回答,它确实描述了我需要理解的内容,但我想澄清一些事情,在我的“代码示例”中,我没有使用LATERAL VIEW来进行INLINE操作,但它仍然完美地工作了。当您说它“需要”LATERAL VIEW时,您是在说即使我没有在代码中指定,背后仍然会发生LATERAL VIEW吗? - dim_user
2
@dim_user 在 Hive 2.1.1 中测试时,会导致异常:SELECT id, INLINE(array_of_structs) - UDTF 不支持在 SELECT 子句之外使用,也不支持嵌套在表达式中,在 Spark 2.4.5 中,它可以同时使用 INLINE 和 EXPLODE,而且不需要 Lateral View。已编辑答案。 - leftjoin
@dim_user 在Spark中的区别在于,INLINE提取结构元素,而EXPLODE仅返回数组元素集合。没有其他区别。 - leftjoin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接