1. 引言

在前一篇中,解决了Hive表中复杂数据结构平铺化以导入Kylin的问题,但是平铺之后计算广告日志的曝光PV是翻倍的,因为一个用户对应于多个标签。所以,为了计算曝光PV,我们得另外创建视图。

分析需求:

  • 每个DSP上的曝光PV,标签覆盖的曝光PV;
  • 累计曝光PV,累计标签覆盖曝光PV

相当于cube(dsp, tag) + measure(pv),HiveQL如下:

select dsp, tag, count(*) as pv
from ad_view
where view = 'view' and day_time between '2016-04-18' and '2016-04-24'
group by dsp, tag with cube;

现在问题来了:如何将原始表中的tags array<struct<tag:string,label:string,src:string>> 转换成有标签(taged)、无标签(empty)呢?显而易见的办法,为字段tags写一个UDF来判断是否有标签。

2. 实战

基本介绍

user-defined function (UDF)包括:

  • 对于字段进行转换操作的函数,如round()、abs()、concat()等;
  • 聚集函数user-defined aggregate functions (UDAFs),比如sum()、avg()等;
  • 表生成函数user-defined table generating functions (UDTFs),生成多列或多行数据,比如explode()、inline()等

UDTF的使用在与select语句使用时受到了限制,比如,不能与其他的列组合出现:

hive> SELECT name, explode(subordinates) FROM employees;
FAILED: Error in semantic analysis: UDTF's are not supported outside the SELECT clause, nor nested in expressions

Hive提供LATERAL VIEW关键字,对UDTF的输入进行包装(wrap),如此可以达到列组合的效果:

hive> SELECT name, sub
> FROM employees
> LATERAL VIEW explode(subordinates) subView AS sub;

UDF与GenericUDF

org.apache.hadoop.hive.ql.exec.UDF是字段转换操作的基类,提供对于简单数据类型进行转换操作。在实现转换操作时,需要重写evaluate()方法。较UDF抽象类,org.apache.hadoop.hive.ql.udf.generic.GenericUDF提供更为复杂的处理方法类,包括三个方法:

  • initialize(ObjectInspector[] arguments),检查输入参数的类型、确定返回值的类型;
  • evaluate(DeferredObject[] arguments),字段转换操作的实现函数,其返回值的类型与initialize方法中所指定的返回类型保持一致;
  • getDisplayString(String[] children),给Hadoop任务展示debug信息的。

判断tags array<struct<tag:string,label:string,src:string>>是否为空标签(EMPTY)的UDF实现如下:

@Description(name = "checkTag",value = "_FUNC_(array<struct>) - from the input array of struct "+"returns the TAGED or EMPTY(no tag).",extended = "Example:\n"+ " > SELECT _FUNC_(tags_array) FROM src;")
public class CheckTag extends GenericUDF {private ListObjectInspector listOI;public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {if (arguments.length != 1) {throw new UDFArgumentLengthException("only takes 1 arguments: List<T>");}ObjectInspector a = arguments[0];if (!(a instanceof ListObjectInspector)) {throw new UDFArgumentException("first argument must be a list / array");}this.listOI = (ListObjectInspector) a;if(!(listOI.getListElementObjectInspector() instanceof StructObjectInspector)) {throw new UDFArgumentException("first argument must be a list of struct");}return PrimitiveObjectInspectorFactory.javaStringObjectInspector;}public Object evaluate(DeferredObject[] arguments) throws HiveException {if(listOI == null || listOI.getListLength(arguments[0].get()) == 0) {return "null_field";}StructObjectInspector structOI = (StructObjectInspector) listOI.getListElementObjectInspector();String tag = structOI.getStructFieldData(listOI.getListElement(arguments[0].get(), 0),structOI.getStructFieldRef("tag")).toString();if (listOI.getListLength(arguments[0].get()) == 1 && tag.equals("EMPTY")) {return "EMPTY";}return "TAGED";}public String getDisplayString(String[] children) {return "check tag whether is empty";}}

还需添加依赖:

<dependency><groupId>org.apache.hive</groupId><artifactId>hive-exec</artifactId><version>0.14.0</version><scope>provided</scope>
</dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-common</artifactId><version>2.5.0-cdh5.3.2</version><scope>provided</scope>
</dependency>

编译后打成jar包,放在HDFS上,然后add jar即可调用该UDF了:

add jar hdfs://path/to/udf-1.0-SNAPSHOT.jar;
create temporary function checktag as 'com.hive.udf.CheckTag';create view if not exists yooshu_view
partitioned on (day_time)
as
select uid, dsp, view, click, checktag(tags) as tag, day_time
from ad_base;

转载于:https://www.cnblogs.com/en-heng/p/5462796.html

Hive UDF初探相关推荐

  1. spark hive udf java_【填坑六】 spark-sql无法加载Hive UDF的jar

    /usr/custom/spark/bin/spark-sql --deploy-mode client add jar hdfs://${clusterName}/user/hive/udf/udf ...

  2. hive udf 分组取top1_Hive中分组取前N个值的实现-row_number()

    背景 假设有一个学生各门课的成绩的表单,应用hive取出每科成绩前100名的学生成绩. 这个就是典型在分组取Top N的需求. 解决思路 对于取出每科成绩前100名的学生成绩,针对学生成绩表,根据学科 ...

  3. Impala UDF - Impala调用Hive UDF函数

    Impala 中运行 Hive UDF 场景:部分查询需要快速返回,使用Impala进行快速.复杂的查询 1.简单的UDF函数过滤,判断是否包含"好"字,返回boolean类型 i ...

  4. hive UDF函数取最新分区

    hive UDF函数取最新分区 1.pom文件 <dependencies><!-- https://mvnrepository.com/artifact/org.apache.hi ...

  5. Hive UDF 函数指南

    精选30+云产品,助力企业轻松上云!>>> 点击蓝色"大数据每日哔哔"关注我 加个"星标",第一时间获取大数据架构,实战经验 Hive 内置了 ...

  6. Hive UDF,就这

    摘要:Hive UDF是什么?有什么用?怎么用?什么原理?本文从UDF使用入手,简要介绍相关源码,UDF从零开始. 本文分享自华为云社区<Hive UDF,就这>,作者:汤忒撒. Hive ...

  7. Spark SQL 和 Hive UDF ExceptionInInitializerError getRemoteBlockReaderFromTcp BlockReaderFactory

    文章目录 1.背景 2. hive UDF函数 2. 注册到hive中 3. Spark SQL 4.运行报错 5. HDFS读取问题? 6. 牛 ???????? 7 . 解决后在谷歌搜索发现 8. ...

  8. Hive UDF开发

    Hive进行UDF开发十分简单,此处所说UDF为Temporary的function,所以需要hive版本在0.4.0以上才可以. Hive的UDF开发只需要重构UDF类的evaluate函数即可.例 ...

  9. hive UDF 根据ip解析地理位置信息

    hive UDF 根据ip查询对应地理位置信息 hive UDF 根据ip查询对应地理位置信息 具体实现 源码 hive UDF 根据ip查询对应地理位置信息 最终效果 具体可返回信息:洲,国家,省, ...

最新文章

  1. Java中JSON字符串与java对象的互换实例详解
  2. tp数据库表大写命名的一些问题
  3. 64位linux安装mysql数据库吗_CentOS7 64位安装mysql教程
  4. Lisenter笔记
  5. 【OpenCV 例程200篇】45. 图像的灰度直方图
  6. 精通Android自定义View(十六)invalidate方法和requestLayout方法
  7. 让AI打工!搜狗全体员工于3月12日狗胜节放假一天
  8. mongodb ssl java_MongoDB自签名SSL连接:SSL对等证书验证失败
  9. 数据库MySQL--常见基础命令
  10. java hashmap用法_备战金九银十:Java核心技术面试题100+,助你搞定面试官
  11. 多种方法实现二叉树的先序、中序、后序、层序遍历
  12. java list 排序_java 对list进行排序
  13. python装饰器 练习
  14. #HTTP协议学习# (六)代理
  15. hadoop 学习
  16. c语言中gotoxy,关于gotoxy的问题....
  17. 手机编程软件推荐(C/C++、JAVA篇)
  18. 通过php上传和下载rar/zip压缩文件
  19. 微信小程序中可以使用calc 函数用于动态计算长度值。
  20. php设置时区的两种方法

热门文章

  1. Oracle事务处理—隔离级别
  2. 传递字符串_一道经典面试题:字符串在Java中如何通过“引用”传递
  3. 哪个牌子的平板电脑好_中山密码锁哪个牌子好
  4. Python制作当年第一款手机游戏-贪吃蛇游戏(练习)
  5. MySQL 源码 需要 什么基础_MySQL 基础之 源码 部署
  6. ucint核心边缘分析_5G、云计算、物联网与边缘计算的相辅相承
  7. 如何清空DNS缓存Windowslinux
  8. Python绘制桑基图
  9. php7 mysql 卡顿_不要在PHP7中踩这些坑
  10. oracle+linux+oel+6.9,用SecureCRT+Xming轻松远程实现linux的X DISPLAY