欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Kylin实战】Hive复杂数据类型与视图

程序员文章站 2022-07-14 14:39:40
...

1. 引言

在分析广告日志时,会有这样的多维分析需求:

  • 曝光、点击用户分别有多少?
  • 标签能覆盖多少广告用户?
  • 各个标签(标注)类别能覆盖的曝光、点击在各个DSP上所覆盖的用户数
  • ……

广告数据与标签数据join之后,存储orc file的schema如下:

create external table default.ad_tag
(
uid string
,dsp string
,view string
,click string
,tags array<struct<tag:string,label:string,src:string>>
)
partitioned by (day_time date)
stored as orc
location '/<path>/<to>';

用户可能会有多个标签,因此采用array<struct>数据类型来作为用户的标签字段。可是,当用Kylin做多维分析时,会出现问题——Kylin只能导入扁平化的Hive表,简而言之,其不支持Hive的复杂数据类型,如array、struct、map等。为了解决这个问题,我们希望能从这张ad_tag表中抽象出一张扁平化的逻辑表,并且这张逻辑表的partition能跟ad_tag表保持同步更新。

2. 视图

众所周知,在RDBMS中,视图(view)可用来抽象出逻辑表,比如,得到CS系所开设的所有课程及相关教师信息:

create view as
    select course, teacher, building
    from teaches, teacher_table
    where teaches.teacher_id = teacher_table.teacher_id 
        and teaches.dept_name = 'CS'

在有一些数据库解决方案中提供了物化视图(materialize view),即物理存储视图。同RDBMS一样,Hive也提供视图,但视图不能被物化。在Hive中创建视图时,只是将该视图的元信息写进metastore;只有在执行引用视图语句时,才会触发其select子句的执行。虽然Hive不能物化视图,但提供了其等价解决方案——由一张表生成另外一张表:

create table
as select ...

这种类物化的方式,在创建表时会触发select子句的执行,存在缺点:对于partition增量更新表,做不到view的partition与之同时更新。所以,对于我们的场景不太适用。

3. inline

如何在创建视图时,将复杂数据类型平铺开来呢?Hive内置UDTF做这种平铺化(flatten)操作,但是UDTF并不能配合select用,而在lateral view子句中使用;比如,explode平铺array:

select pageid, adid
from pageAds 
lateral view explode(adid_list) adTable as adid;

inline平铺array<struct>

select *
from test_bid 
lateral view inline(tags) tag_table_1;

4. Partition

数据在增量更新,对应地partition也在变化,创建的视图也应同步partition的变化;并且,Kylin的增量cube是根据hive表的partition进行refresh的。因此,该视图应保持与基础表相同的partition。正好,Hive提供PartitionedView,为view添加partition。完整地创建视图的命令如下:

create view if not exists ad_tag_view
partitioned on (day_time)
as
select uid, dsp, view, click, tag, label, src, day_time
from ad_tag lateral view inline(tags) tags_table;

经测试,在Kylin中读取view没问题,基础表的增量更新,也会同步地反映到view中。至此,Kylin导入复杂数据类型的Hive表问题已解决。此外,这篇文章《Kylin实践之使用Hive视图》介绍几种不同场景下使用视图的例子。