Hive中的用户自定义函数UDF
Hive中的自定义函数允许用户扩展HiveQL,是一个非常强大的功能。Hive中具有多种类型的用户自定义函数。show functions命令可以列举出当前Hive会话中的所加载进来的函数,包括内置的以及用户加载的函数。
函数都有自身的使用文档,使用describe function命令就可以展示对应函数基本介绍。
标准函数UDF
用户自定义函数指的是一行数据中的一列或是多列数据作为参数然后返回结果是一个值的函数。这里用一个例子作为说明,我们当前有些数据表中存储的时间戳是以秒为单位的long值,如果想将这个long值转换为当天的hour值,就需要写一个UDF(尽管这个需求可以通过Hive中的标准函数解决...但我们举个例子)。
简单的UDF编写,直接继承org.apache.hadoop.hive.ql.exec.UDF,并实现evaluate方法,其中UDF抽象类中并没有严格要求evaluate的方法签名,这意味着可以使用Java中的重载,这样在实际使用时会根据传输参数的类型选择合适的方法;对于每行输入都会调用到evaluate函数,处理后的结果返回给Hive。
public class ToHourFunction extends UDF{
public String evaluate(String timeMillis) {
long longTimeMillis = Long.parseLong(timeMillis);
Date date = new Date(longTimeMillis * 1000L);
return String.format("%tk", date);
}
}
对于自定的UDF,为了让其他人在使用时能够得到一些帮助信息,最好添加@Description注解。注解中包含了这个函数的文档说明,用户也需要这个注解来说明自定义UDF如何使用,比如添加下面的注解:
@Description(name = "to_hour", value = "_FUNC_(x) - return long time millis(plus 1000) to current hour",
extended = "Example: to_hour(123232343) ")
value中的_FUNC_会被替换成用户为这个函数定义的“临时”函数名称,当添加这个jar包,并添加这个自定义函数,将其命名为to_hour
create temporary function to_hour as 'test.udf.ToHourFunction';
添加完成后,执行show functions命令就会额外添加一个我们的自定义函数,使用describe function to_hour能够显示出函数的具体使用方法(@Description中的内容)
to_hour(x) - return long time millis(plus 1000) to current hour
通过使用describe function extended to_hour可以显示@Descrption中的extended属性内容:
Example: to_hour(123232343)
除了UDF类,Hive还提供了一个对应的称为GenericUDF的类,GenericUDF是更为复杂的抽象概念,但是支持更好的null值处理。在Hive中本身就有很多函数是用GenericUDF实现的,我们可以参考他们的写法,比如GenericUDFAbs就是对一些基本的数据类型(SHORT/BYTE/INT/LONG/DOUBLE/FLOAT/STRING/DECIMAL)取绝对值的函数。
比如上面同样的to_hour函数,我们可以用GenericUDF重写一遍。继承GenericUDF函数之后,需要实现三个方法。
首先,initialize方法作为初始化使用,这个方法的目标是确定函数的参数类型,如果参数的数量以及类型不合法,要抛出异常以给用户必要的提示。to_hour方法中,我们需要界定输入参数必须为long类型,参数数量为1个,输出的结果为int类型。
private IntWritable resultInt = new IntWritable();
private ObjectInspectorConverters.Converter inputConverter; @Override
public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
if (arguments.length != 1) {
throw new UDFArgumentLengthException(
"to_hour requires 1 argument, got " + arguments.length);
} if (arguments[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {
throw new UDFArgumentException(
"to_hour only takes primitive types, got " + arguments[0].getTypeName());
}
PrimitiveObjectInspector argumentOIs = (PrimitiveObjectInspector) arguments[0];
PrimitiveObjectInspector.PrimitiveCategory inputType = argumentOIs.getPrimitiveCategory();
if (inputType != PrimitiveObjectInspector.PrimitiveCategory.LONG) {
throw new UDFArgumentTypeException(0, "Argument type should be long");
}
inputConverter = ObjectInspectorConverters
.getConverter(arguments[0], PrimitiveObjectInspectorFactory.writableLongObjectInspector);
return PrimitiveObjectInspectorFactory.writableIntObjectInspector;
}
方法evaluate的输入是一个DeferredObject[],通过initialize方法初始化的inputConverter将DeferredObject转换成对应的Writable对象,这一步中如果输入参数类型可变的话,这个inputConverter的意义就比较重大了,这一点请参考Hive中Abs函数的实现。后面就是将这个数据写到可重用的IntWritable对象中。
@Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
Object valueObj = arguments[0].get();
if (valueObj == null) {
return null;
}
valueObj = inputConverter.convert(valueObj);
long mills = ((LongWritable) valueObj).get() * 1000L;
String hourString = String.format("%tk", new Date(mills));
int hour = Integer.parseInt(hourString);
resultInt.set(hour);
return resultInt;
}
最后一个需要实现的方法是getDisplayString(),用在Hadoop Task内部,在使用此函数时显示调试信息。
@Override
public String getDisplayString(String[] children) {
StringBuilder sb = new StringBuilder();
sb.append("to_hour(");
if (children.length > 0) {
sb.append(children[0]);
for (int i = 1; i < children.length; i++) {
sb.append(",");
sb.append(children[i]);
}
}
sb.append(")");
return sb.toString();
}
截止目前,我们写的函数都只能创建为temp函数,如果想加入到Hive本身作为系统的不变函数使用,就需要修改org.apache.hadoop.hive.ql.exec.FunctionRegistry中的static静态块,将我们的函数加入进去,并重新编译部署hive(当然比较麻烦,不过仅需要替换hive-exec-版本号.jar文件即可)。稍微简单并灵活的方法是,我们写一个公用的shell加载脚本,每个hiveql文件在头上手动加载这个脚本,将公用的函数库加入进去。
Hive中的用户自定义函数UDF的更多相关文章
- Hive中的用户自定义函数
1.1 关于自定义函数 1)Hive 自带了一些函数,比如:max/min等,但是数量有限,自己可以通过自定义UDF来方便的扩展. 2)当Hive提供的内置函数无法满足你的业务处理需要时,此时就可以考 ...
- Hive 文件格式 & Hive操作(外部表、内部表、区、桶、视图、索引、join用法、内置操作符与函数、复合类型、用户自定义函数UDF、查询优化和权限控制)
本博文的主要内容如下: Hive文件存储格式 Hive 操作之表操作:创建外.内部表 Hive操作之表操作:表查询 Hive操作之表操作:数据加载 Hive操作之表操作:插入单表.插入多表 Hive语 ...
- Spark SQL 用户自定义函数UDF、用户自定义聚合函数UDAF 教程(Java踩坑教学版)
在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...
- SparkSQL中的自定义函数UDF
在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...
- SQL Server在用户自定义函数(UDF)中使用临时表
SQL Server在用户自定义函数中UDF使用临时表,这是不允许的. 有时是为了某些特殊的场景, 我们可以这样的实现: CREATE TABLE #temp (id INT) GO INSERT I ...
- 详解Spark sql用户自定义函数:UDF与UDAF
UDAF = USER DEFINED AGGREGATION FUNCTION Spark sql提供了丰富的内置函数供猿友们使用,辣为何还要用户自定义函数呢?实际的业务场景可能很复杂,内置函数ho ...
- 样条函数后续(java)--可在hive中执行的函数
之前写的样条插值算法只能在本地执行,但是我想要的是可在hive中执行的jar包,为了符合我的要求,经过痛苦.气愤.悲伤等一系列过程,终于实现了: 想要实现可在hive中执行的jar包,以下是具体步骤: ...
- hive中内置函数
查看函数的详细使用方法 desc function extended 函数名 例如: 1).desc function extended locate locate(substr, str[, pos ...
- php中调用用户自定义函数的方法:call_user_func,call_user_func_array
看UCenter的时候有一个函数call_user_func,百思不得其解,因为我以为是自己定义的函数,结果到处都找不到,后来百度了一下才知道call_user_func是内置函数,该函数允许用户调用 ...
随机推荐
- lcx端口转发 linux版
一.端口转发使用 1.攻击机上执行以下命令 ./lcx -p1 -p2 -m 在本地监听3389端口,并将发送到本机3389端口的数据传递到本机2222端口 2.跳板机上执行以下命令 ./lcx -h ...
- APUE学习笔记——3.10文件共享
基本概念 内核使用3个数据结构描述一个打开的文件:进程表.文件表.V节点表 首先了解3种数据结构的概念 1 进程表 每一个进程有一个进程表.进程表里是一组打开的文件描述符,如标 ...
- Xss测试
<Script>alert(“XSS attack available!”);</Script>
- 大牛deep learning入门教程
雷锋网(搜索"雷锋网"公众号关注)按:本文由Zouxy责编,全面介绍了深度学习的发展历史及其在各个领域的应用,并解释了深度学习的基本思想,深度与浅度学习的区别和深度学习与神经网络之 ...
- arduino 编程基础
0. setup() 与 loop() 函数 void setup(): // put your setup code here, to run once: 仅执行一次: void loop(): / ...
- git rebase 的作用
git rebase,顾名思义,就是重新定义(re)起点(base)的作用,即重新定义分支的版本库状态.要搞清楚这个东西,要先看看版本库状态切换的两种情况: 我们知道,在某个分支上,我们可以通过git ...
- enum枚举类型的定义
enum枚举类型的定义方式与某种用法 #include <iostream> using namespace std; int main() { enum TOT{ zero, one, ...
- Filter学习(三)Filter(过滤器)常见应用
一.统一全站字符编码 通过配置参数charset指明使用何种字符编码,以处理Html Form请求参数的中文问题: package com.web.filter; import java.io.IOE ...
- CF1109B Sasha and One More Name
CF1109B Sasha and One More Name 构造类题目.仔细看样例解释能发现点东西? 结论:答案只可能是 \(Impossible,1,2\) . \(Impossible:\) ...
- Vijos1891 学姐的逛街计划 【费用流】*
Vijos1891 学姐的逛街计划 描述 doc 最近太忙了, 每天都有课. 这不怕, doc 可以请假不去上课. 偏偏学校又有规定, 任意连续 n 天中, 不得请假超过 k 天. doc 很忧伤, ...