DSP

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

2019-07-13 15:34发布

1. 引言

在分析广告日志时,会有这样的多维分析需求:
  • 曝光、点击用户分别有多少?
  • 标签能覆盖多少广告用户?
  • 各个标签(标注)类别能覆盖的曝光、点击在各个DSP上所覆盖的用户数
  • ……
广告数据与标签数据join之后,存储orc file的schema如下: create external table default.ad_tag ( uid string ,dsp string ,view string ,click string ,tags array> ) partitioned by (day_time date) stored as orc location '//'; 用户可能会有多个标签,因此采用array数据类型来作为用户的标签字段。可是,当用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平铺arrayselect * 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视图》介绍几种不同场景下使用视图的例子。