一、了解它们
- 系统内置函数无法解决实际的业务问题,需要开发者自己编写函数实现自身的业务实现诉求。
- 应用场景非常多,面临的业务不同导致个性化实现很多,故很需要。
二、udf
udf:用户定义(普通)函数,只对单行数值产生作用
特点:一进一出
实现步骤:(java创建自定义udf类)
1、自定义一个java类
2、继承udf类
3、重写evaluate方法
4、打包类所在项目一个all-in-one(所有依赖)的jar包上传到hive所在机器
5、在hive中执行add jar操作,将jar加载到classpath中
6、在hive中创建模板函数,使得可以像使用内嵌函数一样使用这个函数
案例如下:
/**
* @function 自定义UDF统计最小值
*
*/
public class Min extends UDF {
public Double evaluate(Double a, Double b) {
if (a == null)
a = 0.0;
if (b == null)
b = 0.0;
if (a >= b) {
return b;
} else {
return a;
}
}
}
三、udaf
udaf:用户定义聚合函数,可对多行数据产生作用;等同与SQL中常用的SUM(),AVG(),也是聚合函数;
特点:多进一出
实现步骤:
1、自定义一个java类
2、继承UDAF类
3、内部定义一个静态类,实现UDAF Evalutor接口
4、实现方法init,iterate,teminatePartial,merge,terminate五个方法,见下图
5、在hive中执行add jar操作,将jar加载到classpath中
6、在hive中创建模板函数,使得可以像使用内嵌函数一样使用这个函数
案例如下:
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.hadoop.hive.ql.exec.UDAF;
import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
import org.apache.log4j.Logger;
/**
* 实现多条数据合并成一条数据
*/
// 主类继承UDAF
public class StudentScoreAggUDAF extends UDAF {
// 日志对象初始化
public static Logger logger = Logger.getLogger(StudentScoreAggUDAF.class);
// 静态类实现UDAFEvaluator
public static class Evaluator implements UDAFEvaluator {
// 设置成员变量,存储每个统计范围内的总记录数
private Map<String, String> courseScoreMap;
//初始化函数,map和reduce均会执行该函数,起到初始化所需要的变量的作用
public Evaluator() {
init();
}
// 初始化函数间传递的中间变量
public void init() {
courseScoreMap = new HashMap<String, String>();
}
//map阶段,返回值为boolean类型,当为true则程序继续执行,当为false则程序退出
public boolean iterate(String course, String score) {
if (course == null || score == null) {
return true;
}
courseScoreMap.put(course, score);
return true;
}
/**
* 类似于combiner,在map范围内做部分聚合,将结果传给merge函数中的形参mapOutput
* 如果需要聚合,则对iterator返回的结果处理,否则直接返回iterator的结果即可
*/
public Map<String, String> terminatePartial() {
return courseScoreMap;
}
// reduce 阶段,用于逐个迭代处理map当中每个不同key对应的 terminatePartial的结果
public boolean merge(Map<String, String> mapOutput) {
this.courseScoreMap.putAll(mapOutput);
return true;
}
// 处理merge计算完成后的结果,即对merge完成后的结果做最后的业务处理
public String terminate() {
return courseScoreMap.toString();
}
}
}
四、udtf
udtf:用户定义表生成函数,用来解决输入一行输出多行;往往被lateral view explode()+udf等替代实现,比直接用udtf会更简单、直接一些
特点:一进多出
实现步骤:
1、自定义一个java类
2、继承GenericUDTF类1
3、实现initialize(手动覆盖)、process(必须实现)、close(必须实现)方法,手动覆盖如下
public StructObjectInspector initialize(StructObjectInspector argOIs)
throws UDFArgumentException { }
lateral view explode:
select user_id -- 原字段
,user_layer -- 原字段
,ordr_id -- 拆分字段
from A
lateral view explode(ordr_set)tmp1 as ordr_id
使用lateral view的时候需要注意的几点:
1. lateral view的位置是from后where条件前;
2. 生成的虚拟表的表名不可省略;
3. from后可带多个lateral view;
4. 如果要拆分的字段有null值,需要使用lateral view outer 替代,避免数据缺失,这个坑我在工作中踩过!
97在职大数据,开发看心情整理一些干货,欢迎关注和分享!欢迎探讨学习!