Hive中的复杂数据类型,比如array,struct, map能进行大小的比较吗,我们先来做实验看看结果。
Array
select
max(arr)
from (
select array(1,3,5) as arr
union all
select array(2,4,1) as arr
union all
select array(2,3,5) as arr
union all
select array(2,4,0) as arr
union all
select array(2,4,1,0) as arr
)a
的到的结果是[2,4,1,0]
Struct
select
max(str)
from (
select named_struct('a', 1, 'b', 3, 'c', 5) as str
union all
select named_struct('a', 2, 'b', 4, 'c', 1) as str
union all
select named_struct('a', 2, 'b', 3, 'c', 5) as str
union all
select named_struct('a', 2, 'b', 4, 'c', 0) as str
-- union all (struct必须结构相同才能union在一起)
-- select named_struct('a', 2, 'b', 4, 'c', 1, 'd', 0) as str
)a
得到的结果是{"a":2,"b":4,"c":1}
Map
select
max(m)
from (
select map('a', '1', 'b', '3', 'c', '5') as m
union all
select map('a', '2', 'b', '4', 'c', '1') as m
union all
select map('a', '2', 'b', '3', 'c', '5') as m
union all
select map('a', '2', 'b', '4', 'c', '0') as m
union all
select map('a', '2', 'b', '4', 'c', '1') as m
)a
这个会抛出异常:UDFArgumentTypeException Cannot support comparison of map<> type or complex type containing map<>.
那么hive内部具体是怎么进行复杂数据类型的比较的呢,通过github上hive的仓库可以看到执行比较的逻辑只有一句话ObjectInspectorUtils.compare()
>
那我们就看一下ObjectInspectorUtils这个类里面具体的实现。
首先是compareSupported,链接

可以看到这里面基础数据类型都是支持的,数组和结构体如果里面是基础数据类型可以支持,而MAP是不支持的,这和我们的实验结果是一致的。
Struct和Array的比较逻辑在下面一点的位置

它俩的逻辑是相似的,每个元素按照顺序进行比较,数组自然就是按照位置从小到大,结构体是按照Schema的定义顺序从左到右。如果出现不相等的情况就分出了大小;否则按照长度本身进行比较,长的大、短的小。
这一段逻辑还是非常有意思,因为平时很少会遇到对复杂数据类型进行比较的情况。了解了之后就能在一些特殊情况下应用起来,比如把每一行组装成一个struct,struct中的第一个元素放用户的访问时间,就可以用max()找到用户的第一条访问记录而不用row_number()窗口函数,执行效率就可能会有些许的提高。
注意这里虽然会对每一个元素进行比较,但是这里也是不行直接用来进行二级排序的~
本文探讨了Hive中如何比较复杂数据类型,如Array、Struct和Map。通过实验得出,Array和Struct在内部元素为基本数据类型时可以比较,但Map会抛出异常。深入Hive源码发现,比较逻辑主要针对基本数据类型,对于Array和Struct,比较基于元素顺序。了解这种比较机制有助于在特殊场景下优化查询,例如用struct的访问时间进行排序以找到用户第一条访问记录,但不能直接用于二级排序。
627

被折叠的 条评论
为什么被折叠?



