参考文章:

1.UDF,UDAF,UDTF区别

UDF:最简单的自定义,实现一对一,输入一行数据输出一行数据
UDAF:自定义聚合函数,实现多对一,输入多行数据输出一行数
UDTF:用来实现一行输入多行输出,这次先不讲

2.UDF开发

要点:1.UDF类需要继承org.apache.hadoop.hive.ql.exec.UDF.

2.UDF类需要实现evaluate类.

UDF开发实例:

开发一个udf getdate以返回当前系统时间

package udf.test;
import org.apache.hadoop.hive.ql.exec.UDF; import java.text.SimpleDateFormat;
import java.util.Date; public class Getdate extends UDF {
public String evaluate(){
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}
}

然后maven打包:mvn clean compile.package

接着把包放到服务器上,比如放到/home/azkaban/UDF/udf-jar.1.1.0

进入hive shell,执行add jar /home/azkaban/UDF/udf-jar.1.1.0

接着执行create tempopary function getdate as 'udf.test.Getdate';

这里的getdate就是function名称。在hive shell中执行select getdate()就会返回当前的系统时间。

待解决:hive中类似于bigint的类型,在udf的evaluate方法中如何返回,改成long?

3.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的运行流程简介

其实hive就是对MapReduce的一层包装,所以我们写UDAF的时候可以通过对应到Map Reduce进行理解。

UDAF的四个阶段

  • PARTIAL1:原始数据到部分聚合,调用iterate和terminatePartial --> map阶段
  • PARTIAL2: 部分聚合到部分聚合,调用merge和terminatePartial --> combine阶段
  • FINAL: 部分聚合到完全聚合,调用merge和terminate --> reduce阶段
  • COMPLETE: 从原始数据直接到完全聚合 --> map阶段,并且没有reduce

    除了上面提到的iterate,merge,terminatePartial以外,还有init(初始化并返回,返回值的类型) ,getNewAggregationBuffer(获取新的buffer,也就是方法间传递参数的对象),reset(重置buffer对象)

UDAF需要实现的方法

在四个阶段中,我们可以得知,需要实现7个方法

  • init:这个方法不写会报错:fatal: nullpointexception null
  • getNewAggregationBuffer:我们定义一个对象,在这个方法里面实现该对象以用于参数传递
  • reset:重置buffer对象
  • iterate:类似于map()
  • merge:类似于Reduce()
  • terminatePartial:返回部分聚合数据的持久化对象。因为调用这个方法时,说明已经是map或者combine的结束了,必须将数据持久化以后交给reduce(也就是调用merge)进行处理。
  • terminate:结束,生成最终结果。

对象实例

  • 现要求实现某个字段以","进行提取的函数wm_concat,比如.

table:customers

name gender age
张三 23
李氏 26
王婆 54
尼古拉斯-赵六 43

select wm_concat(name) from customers;

返回的是 "张三,李氏,王婆,尼古拉斯-赵六"

  • 代码如下:
package com.maihaoche.baiyan.UDF;

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.parse.SemanticException;
import org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFParameterInfo;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.io.Text; public class Wm_concat extends AbstractGenericUDAFResolver{
@Override
public GenericUDAFEvaluator getEvaluator(GenericUDAFParameterInfo info) throws SemanticException {
return new GenericUDAFWmconcatEvaluator();
} public static class GenericUDAFWmconcatEvaluator extends GenericUDAFEvaluator{ static class stringagg implements AggregationBuffer{
StringBuffer stringBuffer=new StringBuffer();
String flag=null;
boolean empty;
} @Override
/*
init方法不写的话会报nullpointexception null 的错误
*/
public ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException {
super.init(m, parameters);
if(parameters.length!=1){
throw new UDFArgumentException("Argument Exception");
}
return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
} /*
获取存放中间结果的对象
*/
public AggregationBuffer getNewAggregationBuffer() throws HiveException {
stringagg sa=new stringagg();
String str=null;
return sa;
}
public void reset(AggregationBuffer aggregationBuffer) throws HiveException {
stringagg sa=(stringagg)aggregationBuffer;
sa.empty=true;
sa.stringBuffer.delete(0,sa.stringBuffer.length());
} public void iterate(AggregationBuffer aggregationBuffer, Object[] objects) throws HiveException {
if(objects.length !=1 ){
throw new UDFArgumentException("Argument Exception");
}
this.merge(aggregationBuffer,objects[0]);
} public Object terminatePartial(AggregationBuffer aggregationBuffer) throws HiveException {
return this.terminate(aggregationBuffer);
} public void merge(AggregationBuffer aggregationBuffer, Object o) throws HiveException {
stringagg sa=(stringagg)aggregationBuffer;
if(o!=null){
sa.stringBuffer.append(o.toString());
sa.empty=false;
}
} public Object terminate(AggregationBuffer aggregationBuffer) throws HiveException {
stringagg sa=(stringagg)aggregationBuffer;
if(sa.empty==true) return null;
int length=sa.stringBuffer.toString().length();
return new Text(sa.stringBuffer.toString().substring(0,length-1));//通过substring解决最后一个字段跟着的分隔符
}
}
}

很明显,我们可以看出来,AbstractGenericUDAFResolver就是一层皮,我们可以在里面加一写验证条件,比如:

检测下面就进行检测是否有2个参数以及判断数据类型

 public GenericUDAFEvaluator getEvaluator(GenericUDAFParameterInfo 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.");
}

待解决:如何写希望输入的是两个参数的,比如现在希望自己指定wm_concat的分割符。

UDF/UDAF开发总结的更多相关文章

  1. Hive UDAF开发之同时计算最大值与最小值

    卷首语 前一篇文章hive UDAF开发入门和运行过程详解(转)里面讲过UDAF的开发过程,其中说到如果要深入理解UDAF的执行,可以看看求平均值的UDF的源码 本人在看完源码后,也还是没能十分理解里 ...

  2. hive UDAF开发入门和运行过程详解(转)

    介绍 hive的用户自定义聚合函数(UDAF)是一个很好的功能,集成了先进的数据处理.hive有两种UDAF:简单和通用.顾名思义,简单的UDAF,写的相当简单的,但因为使用Java反射导致性能损失, ...

  3. Hive UDAF开发详解

    说明 这篇文章是来自Hadoop Hive UDAF Tutorial - Extending Hive with Aggregation Functions:的不严格翻译,因为翻译的文章示例写得比较 ...

  4. Hive 自定义函数 UDF UDAF UDTF

    1.UDF:用户定义(普通)函数,只对单行数值产生作用: 继承UDF类,添加方法 evaluate() /** * @function 自定义UDF统计最小值 * @author John * */ ...

  5. hive UDAF开发和运行全过程

    介绍 hive的用户自定义聚合函数(UDAF)是一个很好的功能,集成了先进的数据处理.hive有两种UDAF:简单和通用.顾名思义,简单的UDAF,写的相当简单的,但因为使用Java反射导致性能损失, ...

  6. 简述UDF/UDAF/UDTF是什么,各自解决问题及应用场景

    UDF User-Defined-Function 自定义函数 .一进一出: 背景 系统内置函数无法解决实际的业务问题,需要开发者自己编写函数实现自身的业务实现诉求. 应用场景非常多,面临的业务不同导 ...

  7. [转]HIVE UDF/UDAF/UDTF的Map Reduce代码框架模板

    FROM : http://hugh-wangp.iteye.com/blog/1472371 自己写代码时候的利用到的模板   UDF步骤: 1.必须继承org.apache.hadoop.hive ...

  8. hive中 udf,udaf,udtf

    1.hive中基本操作: DDL,DML 2.hive中函数 User-Defined Functions : UDF(用户自定义函数,简称JDF函数)UDF: 一进一出  upper  lower ...

  9. 【转】HIVE UDF UDAF UDTF 区别 使用

    原博文出自于:http://blog.csdn.net/longzilong216/article/details/23921235(暂时) 感谢! 自己写代码时候的利用到的模板   UDF步骤: 1 ...

随机推荐

  1. python2和python3中列表推导式的变量泄露问题

    Python 2.x 中,在列表推导中 for 关键词之后的赋值操作可能会影响列表推导上下文中的同名变量.像下面这个 Python 2.7 控制台对话: Python 2.7.15 (default, ...

  2. WPF Lambda

    lambda简介 lambda运算符:所有的lambda表达式都是用新的lambda运算符 " => ",可以叫他,“转到”或者 “成为”.运算符将表达式分为两部分,左边指定 ...

  3. Compiler Principle

    1.Einleitung 1.1 Der Überblick über Compiler 1.1.1 Lexikalische Analyse Die lexikalische Analyse zer ...

  4. Scrum 冲刺博客第四篇

    一.当天站立式会议照片一张 二.每个人的工作 (有work item 的ID),并将其记录在码云项目管理中 昨天已完成的工作 新建立了一个list页面用来显示题目,并且创建了列表用来进行题目的存放,将 ...

  5. [PY3]——函数——函数注解 | 实现类型检查功能

    函数注解(Function Annotations)——> 可以在定义函数的时候对参数和返回值添加注解 写函数注解 #平时我们使用help()可以查看一个函数的说明,我们自己写的函数也可以提供这 ...

  6. vue 获取数据联动下拉框select ,并解决报Duplicate value found in v-for="...": "". Use track-by="$index" 错误

    公司项目中遇到一个问题,联动下拉框,并且数据是使用vue-resource从后台获取的,格式不利于输出联动下拉框,联动下拉框是第一个下拉框输出一个数组里每一项json的一个text值,从而第二下拉框输 ...

  7. Nginx 基于客户端 IP 来开启/关闭认证

    前些日子帮助公司在搭建了一个内部资源的导航页面,方便公司员工访问各种常用的系统.因为这个页面包含一些敏感信息,我们希望对其做认证,但仅当从外网访问的时候才开启,当从公司内网访问的时候,则无需输入账号密 ...

  8. 【转载】在Angular 2/Typescript中声明全局变量的最佳方式是什么?

    问题详细描述 我想在Typescript语言中的Angular 2中声明一些全局可见的变量.最佳的实践方法是? 推荐的实现方法 这是最简单的解决方案,无需使用Service或Observer: 将全局 ...

  9. jquery里prop和attr的区别

    本文通过具体的实例来讲述jquery里prop和attr的区别及使用方法. 在jquery里,我们要获取一个标签元素的属性,可以用attr或者prop,那么两者有什么区别呢? 其实很简单: attr可 ...

  10. 实例-sprintf() 函数详解-输出格式转换函数

    Part1:实例 $filterfile = basename(PHP_SELF, '.php'); if (isset($_GET['uselastfilter']) && isse ...