Hive UDAF介绍与开发
UDAF简介
UDAF是用户自定义聚合函数。Hive支持其用户自行开发聚合函数完成业务逻辑。
通俗点说,就是你可能需要做一些特殊的甚至是非常扭曲的逻辑聚合,但是Hive自带的聚合函数不够玩,同时也还找不到高效的等价玩法,那么,这时候就该自己写一个UDAF了。
而从实现上来看,Hive的UDAF分为两种:
- Simple。即继承
org.apache.hadoop.hive.ql.exec.UDAF
类,并在派生类中以静态内部类的方式实现org.apache.hadoop.hive.ql.exec.UDAFEvaluator
接口。这种方式简单直接,但是在使用过程中需要依赖JAVA反射机制,因此性能相对较低。在Hive源码包org.apache.hadoop.hive.contrib.udaf.example
中包含几个示例。可以直接参阅。但是这些接口已经被注解为Deprecated,建议不要使用这种方式开发新的UDAF函数。 - Generic。这是Hive社区推荐的新的写法,以抽象类代替原有的接口。新的抽象类
org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver
替代老的UDAF接口,新的抽象类org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator
替代老的UDAFEvaluator接口。
产生这两种方式的原因并不高深,就是结构演进,历史遗留。原文链接最后一段说明了一下演进的版本以及原因。
UDAF相关类和接口简介
AbstractGenericUDAFResolver
:该抽象类实现了GenericUDAFResolver2
的接口。UDAF主类须继承该抽象类,其主要作用是实现参数类型检查和操作符重载。可以为同一个函数实现不同入参的版本。org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator
:该抽象类为UDAF具体的逻辑处理,包括几个必须实现的抽象方法,这几个方法负责完成UDAF所需要处理的逻辑。
UDAF的运行流程简介
抽象类GenericUDAFEvaluator
中,包含一个静态内部枚举类,和一系列抽象方法。这个枚举类的注释中,解释了各个枚举值的运行阶段和运行内容。按照时间先后顺序,分别有:
- PARTIAL1:原始数据到部分聚合,调用iterate和terminatePartial --> map阶段
- PARTIAL2: 部分聚合到部分聚合,调用merge和terminatePartial --> combine阶段
- FINAL: 部分聚合到完全聚合,调用merge和terminate --> reduce阶段
- COMPLETE: 从原始数据直接到完全聚合 --> map阶段,并且没有reduce
那么,这几个方法分别干了些啥呢?
init
: 实例化Evaluator类的时候调用的,在不同的阶段需要返回不同的OI。其入参和返回值,以及Mode阶段的关系如下表:入参 返回值的使用者 P1 原始数据 terminatePartial P2 部分聚合数据 terminatePartial F 部分聚合数据 terminate C 原始数据 terminate getNewAggregationBuffer
: 获取存放中间结果的对象iterate
:处理一行数据terminatePartial
:返回部分聚合数据的持久化对象。因为调用这个方法时,说明已经是map或者combine的结束了,必须将数据持久化以后交给reduce进行处理。只支持JAVA原始数据类型及其封装类型、HADOOP Writable类型、List、Map,不能返回自定义的类,即使实现了Serializable也不行,否则会出现问题或者错误的结果。merge
:将terminatePartial
返回的部分聚合数据进行合并,需要使用到对应的OI。terminate
:结束,生成最终结果。
两类UDAF基本原理相同,下面以histogram_numeric
这个系统自带的Generic UDAF为例,描述一下UDAF的运行和开发过程。这个函数涵盖了UDAF多个特性,比如入参类型检查并返回复杂数据类型。
UDAF开发
1. 构造UDAF代码骨架部分
先搭建好代码骨架,完成需要继承的类和接口结构。
public class GenericUDAFHistogramNumeric extends AbstractGenericUDAFResolver {
static final Log LOG = LogFactory.getLog(GenericUDAFHistogramNumeric.class.getName());
@Override
public GenericUDAFEvaluator getEvaluator(GenericUDAFParameterInfo info) throws SemanticException {
// TODO: 1. Type-checking goes here!
return new GenericUDAFHistogramNumericEvaluator();
}
public static class GenericUDAFHistogramNumericEvaluator extends GenericUDAFEvaluator {
// UDAF logic goes here!
}
}
2.实现getEvaluator方法
该方法非常简单,其主要目的是校验UDAF的入参个数和入参类型并返回Evaluator对象。调用者传入不同的参数时,向其返回不同的Evaluator或者直接抛出异常。这部分代码可以写入骨架代码中的TODO:1
处。例如本例中的实现,该UDAF不支持多种参数的版本,限定参数个数必须为2,并且第一个参数必须是简单数据类型,第二个参数必须是int。
@Override
public GenericUDAFEvaluator getEvaluator(TypeInfo[] parameters) throws SemanticException {
if (parameters.length != 2) {
throw new UDFArgumentTypeException(parameters.length - 1,
"Please specify exactly two arguments.");
}
// validate the first parameter, which is the expression to compute over
if (parameters[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {
throw new UDFArgumentTypeException(0,
"Only primitive type arguments are accepted but "
+ parameters[0].getTypeName() + " was passed as parameter 1.");
}
switch (((PrimitiveTypeInfo) parameters[0]).getPrimitiveCategory()) {
case BYTE:
case SHORT:
case INT:
case LONG:
case FLOAT:
case DOUBLE:
case TIMESTAMP:
case DECIMAL:
break;
case STRING:
case BOOLEAN:
case DATE:
default:
throw new UDFArgumentTypeException(0,
"Only numeric type arguments are accepted but "
+ parameters[0].getTypeName() + " was passed as parameter 1.");
}
// validate the second parameter, which is the number of histogram bins
if (parameters[1].getCategory() != ObjectInspector.Category.PRIMITIVE) {
throw new UDFArgumentTypeException(1,
"Only primitive type arguments are accepted but "
+ parameters[1].getTypeName() + " was passed as parameter 2.");
}
if( ((PrimitiveTypeInfo) parameters[1]).getPrimitiveCategory()
!= PrimitiveObjectInspector.PrimitiveCategory.INT) {
throw new UDFArgumentTypeException(1,
"Only an integer argument is accepted as parameter 2, but "
+ parameters[1].getTypeName() + " was passed instead.");
}
return new GenericUDAFHistogramNumericEvaluator();
}
3.实现Evaluator
从骨架代码中,可以看到一个静态内部类实现了Evaluator的抽象类,并且必须实现它的几个抽象方法。这些方法的调用时机即意义参见上面的表格以及GenericUDAFEvaluator
类的静态内部枚举类Mode
。
4. 注册函数
将函数直接写入FunctionRegistry
类的静态代码块中,system.registerGenericUDAF("histogram_numeric", new GenericUDAFHistogramNumeric());
,或者将UDAF代码单独打包成jar,采用CREATE FUNCTION
语句创建函数。
End。
Hive UDAF介绍与开发的更多相关文章
- Hive UDAF开发之同时计算最大值与最小值
卷首语 前一篇文章hive UDAF开发入门和运行过程详解(转)里面讲过UDAF的开发过程,其中说到如果要深入理解UDAF的执行,可以看看求平均值的UDF的源码 本人在看完源码后,也还是没能十分理解里 ...
- Hive UDAF开发详解
说明 这篇文章是来自Hadoop Hive UDAF Tutorial - Extending Hive with Aggregation Functions:的不严格翻译,因为翻译的文章示例写得比较 ...
- Hive 接口介绍(Web UI/JDBC)
Hive 接口介绍(Web UI/JDBC) 实验简介 本次实验学习 Hive 的两种接口:Web UI 以及 JDBC. 一.实验环境说明 1. 环境登录 无需密码自动登录,系统用户名shiyanl ...
- 我的VSTO之路(四):深入介绍Word开发
原文:我的VSTO之路(四):深入介绍Word开发 在上一篇文章中,我介绍了Word的对象模型和一些基本开发技巧.为了更好的介绍Word插件开发,我为本文制作了一个Word书签的增强版,具体功能是让用 ...
- mxgraph进阶(二)mxgraph的初步介绍与开发入门
mxgraph的初步介绍与开发入门 前言 由于小论文实验需求,需要实现根据用户日志提取出行为序列,然后根据行为序列生成有向图的形式,并且连接相邻动作的弧上标有执行此次相邻动作的频次.为此,在大师兄徐凯 ...
- 封装:简要介绍自定义开发基于WPF的MVC框架
原文:封装:简要介绍自定义开发基于WPF的MVC框架 一.目的:在使用Asp.net Core时,深感MVC框架作为页面跳转数据处理的方便,但WPF中似乎没有现成的MVC框架,由此自定义开发一套MVC ...
- solidity语言介绍以及开发环境准备
solidity语言介绍以及开发环境准备 Solidity 是一门面向合约的.为实现智能合约而创建的高级编程语言.这门语言受到了 C++,Python 和 Javascript 语言的影响,设计的 ...
- MongoDB介绍及开发指南
目录 一.MongoDB介绍 二.搭建MongoDB 三.Java With MongoDB 四.Spring Session MongoDB 五.MongoDB开发规范及示例 六.MongoDB + ...
- hive UDAF开发入门和运行过程详解(转)
介绍 hive的用户自定义聚合函数(UDAF)是一个很好的功能,集成了先进的数据处理.hive有两种UDAF:简单和通用.顾名思义,简单的UDAF,写的相当简单的,但因为使用Java反射导致性能损失, ...
随机推荐
- bzoj 1176 Mokia(CDQ分治,BIT)
[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=96974 [题意] 定义查询操作与修改操作:1 x y z 为 ...
- 《GettingThingsDone》--GTD学习笔记(三)-GTD的三个关键原则
原则一:养成收集的习惯 1.收集习惯给个人带来的好处 在收集过程中你会出现焦虑和解脱,难以招架和控制良好的情绪. (1)消极情绪的来源 要做的事情总比你能做的事情多,要做的事情太多并不 ...
- 50道经典的JAVA编程题(41-45)
50道经典的JAVA编程题(41-45),苦逼的程序猿,晚上睡不着了编程吧~今天坚持做10道题!发现编程能是我快乐...O(∩_∩)O哈哈~能平静我烦乱的心,剩下5道题留到考试完了再做吧!该睡觉了.. ...
- HDU-4612 Warm up 边双连通分量+缩点+最长链
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 简单图论题,先求图的边双连通分量,注意,此题有重边(admin还逗比的说没有重边),在用targ ...
- [Objective-c 基础 - 2.5] NSString
1.NSString基本使用 使用%@占位符输出对象 ; ; NSString *str2 = [NSString stringWithFormat:@"My age is %d and n ...
- 28个你必须知道的HTML5的新特性,技巧以及技术
原文地址:http://adamlu.com/?p=584#header 总结一下: 1. 新的Doctype 尽管使用<!DOCTYPE html>,即使浏览器不懂这句话也会按照标准模式 ...
- Struts2中DMI(动态方法调用)的错误问题(There is no Action mapped for namespace [/xxx] and action name [xxx!yyy] a)
默认的Struts.xml中是这样的 <constant name="struts.enable.DynamicMethodInvocation" value="f ...
- flex开发小技巧集锦
关于flex开发网上有非常多的相关信息介绍,因此我们要想学习关于flex开发的知识信息技能是一件非常简单和方便的事情.而针对于flex开发小编要告诉大家的是一些flex开发小技巧.利用这些小技巧能够有 ...
- Android studio插件安装
Android Studio安装插件的方式其实和Eclipse大同小异.废话不多说,直接上图: 区域1:你当前已经安装了的插件 区域2:在线安装 区域3:从硬盘安装,即针对你已经下载好了的插件,可通过 ...
- jboss7的服务器开启和关闭命令
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...