自定义函数

Hive 自带了一些函数,比如:max/min等,但是数量有限,自己可以通过自定义UDF来方便的扩展。当Hive提供的内置函数无法满足你的业务处理需要时,此时就可以考虑使用用户自定义函数(UDF:user-defined function)。

用户自定义函数类别分为以下三种

  • UDF(User-Defined-Function)

    一进一出

  • UDAF(User-Defined Aggregation Function)

    多进一出;如聚集函数

  • UDTF(User-Defined Table-Generating Functions)

    一进多出;如炸裂函数(explode)

临时函数:只存在当前会话,切换或断开就没有了,和当前use的库没有关系

删除临时函数:drop temporary function 函数名 或者 断开会话

永久函数:和库关联,在创建的时候需要指定库a.函数名,在使用的时候如果当前使用的库就是

编程步骤

(1)官方文档https://cwiki.apache.org/confluence/display/Hive/HivePlugins

(2)继承Hive提供的类

​ 3.x逐渐弃用UDF类,推荐用下面的

​ org.apache.hadoop.hive.ql.udf.generic.GenericUDF

​ org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;

(3)实现类中的抽象方法

(4)在hive的命令行窗口创建函数

添加jar

add jar linux_jar_path

创建function

create [temporary] function [dbname.]function_name AS class_name;

(5)在hive的命令行窗口删除函数

drop [temporary] function [if exists] [dbname.]function_name;

案例

需求

1.创建工程

2.导入依赖

<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>3.1.2</version>
</dependency>

3.创建类

MyLen.java

package com.hive.udf;

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; /**
* @description: 自定义UDF函数类, 求输入数据长度,只能处理一个hive的基本类型参数
* @author: HaoWu
* @create: 2020/6/30 11:39
*/ //hive3.X的UDF类已废除,推荐用GenericUDF
public class MyLen extends GenericUDF {
/**
* 初始化
*
* @param objectInspectors 输入参数类型的鉴别器对象
* @return 返回值类型的鉴别器对象
* @throws UDFArgumentException
*/
@Override
public ObjectInspector initialize(ObjectInspector[] objectInspectors) throws UDFArgumentException {
//判断输入参数的个数
if (objectInspectors.length != 1) {
throw new UDFArgumentLengthException("input args nums Error...");
}
//判断输入参数的类型是否为hive基本类型
if (!objectInspectors[0].getCategory().equals(ObjectInspector.Category.PRIMITIVE)) {
throw new UDFArgumentTypeException(0, "input args type Error...");
}
//函数本身返回int,需要返回int类型的鉴别器对象
return PrimitiveObjectInspectorFactory.javaIntObjectInspector;
} /**
* 函数处理逻辑
*
* @param deferredObjects
* @return
* @throws HiveException
*/
@Override
public Object evaluate(DeferredObject[] deferredObjects) throws HiveException { if (deferredObjects[0].get() == null) {
return 0;
}
Object obj = deferredObjects[0];
int len = obj.toString().length();
return len;
} @Override
public String getDisplayString(String[] strings) {
return "";
}
}

4.打jar包

打包插件

    <build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<!-- 指定主类 -->
<mainClass>com.hive.udf.MyLen</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

打包package,然后改名为mylen_udf.jar

5.上传hive所在服务器

[atguigu@hadoop102 datas]$ tree /opt/module/hive/datas/
/opt/module/hive/datas/
└── my_len.jar

6.将jar添加到hive的classpath

add jar /opt/module/hive/datas/mylen_udf.jar

7.创建临时函数与开发好的java class关联

create temporary function mylenudf as "com.hive.udf.MyLen"

8.测试自定义函数

临时函数和永久函数

创建临时函数

添加jar包的类路径给hive,注意是临时生效

add jar /opt/module/hive/datas/myudf.jar;

创建临时函数

create  temporary function my_len as "com.atguigu.hive.udf.MyStringLength";

删除临时函数

drop  temporary function my_len;

注意:临时函数只跟会话有关系,只要会话不断,在当前会话下,任意一个库都可以使用。其他会话全都不能使用。

创建永久函数

注意:因为永久函数是永久生效的,我们推出当前会话以后,其他会话也要使用永久函数,因此我们就不能简单的使用add jar来添加hive的类路径了

创建永久函数

注意:此时要使用USING JAR的方式来添加函数的jar包类路径,并且这个路径必须是hdfs路径

create function my_len2 as "com.atguigu.hive.udf.MyStringLength" USING JAR 'hdfs://hadoop102:9820/hivejar/myudf.jar';

删除永久函数

drop function my_len2;

注意:永久函数创建的时候,在函数名之前需要自己加上库名,如果不指定库名的话,会默认把当前库的库名给加上。

然后使用永久函数的时候,需要在指定的库里面操作,或者在其他库里面使用的话得加上 库名.函数名

二.UDTF案例

1.创建类

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructField;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.json.JSONArray;
import java.util.ArrayList;
import java.util.List; /**
* @description: UDTF函数功能(类似于explode函数功能)
* 入参:将json数组字符串
* 出参:将json数组的每一个元素作为一行输出
*
* @author: HaoWu
* @create: 2020年08月15日
*/
public class ExplodeJSONArrayUDTF extends GenericUDTF {
/*
初始化方法
*/
@Override
public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
//1.获取传入的参数
List<? extends StructField> inputFields = argOIs.getAllStructFieldRefs();
//2.判断参数个数是否为一个?
if (inputFields.size() != 1) {
throw new UDFArgumentException("只需要一个参数");
}
//3.定义返回值名称和类型
//返回的字段名
List<String> fieldNames = new ArrayList<>();
fieldNames.add("action");
//返回的字段类型
List<ObjectInspector> fieldOIs = new ArrayList<>();
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
} /*
生成返回的数据
*/
@Override
public void process(Object[] objects) throws HiveException {
//1.获取传入的数据
String jsonArray = objects[0].toString();
//2.将string转化为json数组
JSONArray actions = new JSONArray(jsonArray);
//3.循环取出json数组的元素,依次写出
for (int i = 0; i < actions.length(); i++) {
String[] result = new String[1];
result[0]=actions.getString(i);
//写出
forward(result);
}
} @Override
public void close() throws HiveException { }
}

2.打包上传

将hivefunction-1.0-SNAPSHOT.jar上传到hadoop102的/opt/module,然后再将该jar包上传到HDFS的/user/hive/jars路径下

[root@hadoop102 module]$ hadoop fs -mkdir -p /user/hive/jars
[root@hadoop102 module]$ hadoop fs -put warehouse-1.0-SNAPSHOT-jar-with-dependencies.jar /user/hive/jars

3.创建临时函数

hive> create function explode_json_array as 'com.hivescript.ExplodeJSONArrayUDTF' using jar 'hdfs://hadoop102:8020/user/hive/jars/warehouse-1.0-SNAPSHOT-jar-with-dependencies.jar';
Added [/tmp/ca6c5ab9-c76b-406b-9d1f-63aa32523f2f_resources/warehouse-1.0-SNAPSHOT-jar-with-dependencies.jar] to class path
Added resources: [hdfs://hadoop102:8020/user/hive/jars/warehouse-1.0-SNAPSHOT-jar-with-dependencies.jar]
OK
Time taken: 1.093 seconds

4.测试

测试数据

[{"name":"大郎","sex":"男","age":"25"},{"name":"西门庆","sex":"男","age":"47"}]
hive> select explode_json_array('[{"name":"大郎","sex":"男","age":"25"},{"name":"西门庆","sex":"男","age":"47"}]');
OK
{"name":"大郎","sex":"男","age":"25"}
{"name":"西门庆","sex":"男","age":"47"}
Time taken: 2.906 seconds, Fetched: 2 row(s)

注意

如果修改了自定义函数重新生成jar包怎么处理?只需要替换HDFS路径上的旧jar包,然后重启Hive客户端即可。

Hive(九)【自定义函数】的更多相关文章

  1. Hadoop生态圈-hive编写自定义函数

    Hadoop生态圈-hive编写自定义函数 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  2. Hadoop生态圈-Hive的自定义函数之UDTF(User-Defined Table-Generating Functions)

    Hadoop生态圈-Hive的自定义函数之UDTF(User-Defined Table-Generating Functions) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  3. Hadoop生态圈-Hive的自定义函数之UDAF(User-Defined Aggregation Function)

    Hadoop生态圈-Hive的自定义函数之UDAF(User-Defined Aggregation Function) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  4. Hadoop生态圈-Hive的自定义函数之UDF(User-Defined-Function)

    Hadoop生态圈-Hive的自定义函数之UDF(User-Defined-Function) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.

  5. 【Hive】自定义函数

    Hive的自定义函数无法满足实际业务的需要,所以为了扩展性,Hive官方提供了自定义函数来实现需要的业务场景. 1.定义 (1)udf(user defined function):  自定义函数,特 ...

  6. Hive中自定义函数

    Hive的自定义的函数的步骤: 1°.自定义UDF extends org.apache.hadoop.hive.ql.exec.UDF 2°.需要实现evaluate函数,evaluate函数支持重 ...

  7. [Hive_12] Hive 的自定义函数

    0. 说明 UDF //user define function //输入单行,输出单行,类似于 format_number(age,'000') UDTF //user define table-g ...

  8. Hive中如何添加自定义UDF函数以及oozie中使用hive的自定义函数

    操作步骤: 1. 修改.hiverc文件 在hive的conf文件夹下面,如果没有.hiverc文件,手工自己创建一个. 参照如下格式添加: add jar /usr/local/hive/exter ...

  9. Hive(9)-自定义函数

    一. 自定义函数分类 当Hive提供的内置函数无法满足你的业务处理需要时,此时就可以考虑使用用户自定义函数. 根据用户自定义函数类别分为以下三种: 1. UDF(User-Defined-Functi ...

  10. 三 Hive 数据处理 自定义函数UDF和Transform

    三  Hive 自定义函数UDF和Transform 开篇提示: 快速链接beeline的方式: ./beeline -u jdbc:hive2://hadoop1:10000 -n hadoop 1 ...

随机推荐

  1. 理解ASP.NET Core - 文件服务器(File Server)

    注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 提供静态文件 静态文件默认存放在 Web根目录(Web Root) 中,路径为 项目根目录(C ...

  2. python进阶(22)pydantic--数据类型校验

    pydantic库的作用 pydantic库是一种常用的用于数据接口schema定义与检查的库. Pydantic 在运行时强制执行类型提示,并在数据无效时提供用户友好的错误信息. pydantic安 ...

  3. 微信小程序API接口封装

    @ 目录 一,让我们看一下项目目录 二,让我们熟悉一下这三个文件目的(文件名你看着办) 三,页面js中如何使用 今天的API的封装,我们拿WX小程序开发中,对它的API (wx.request)对这个 ...

  4. Python-爬取CVE漏洞库👻

    Python-爬取CVE漏洞库 最近吧准备复现一下近几年的漏洞,一个一个的去找太麻烦了.今天做到第几页后面过几天再来可能就不记得了.所以我想这搞个爬虫给他爬下来做个excel表格,那就清楚多了.奈何还 ...

  5. Linux常用命令和快捷键整理:(2)常用快捷键

    前言: Linux常用快捷键和基本命令整理,先上思维导图: linux常用命令请见:https://www.cnblogs.com/yinzuopu/p/15516499.html 基本快捷键的使用 ...

  6. SpringCloud升级之路2020.0.x版-31. FeignClient 实现断路器以及线程隔离限流的思路

    本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在前面一节,我们实现了 FeignClient 粘合 resilience4j 的 Ret ...

  7. Linux ns 5. IPC Namespace 详解

    文章目录 1. 简介 2. 源码分析 2.1 copy_ipcs() 2.2 ipcget() 2.3 ipc_check_perms() 2.4 相关系统调用 参考文档: 1. 简介 进程间通讯的机 ...

  8. Java学习(二十二)

    学了一个在css中叫font的样式: 感觉还是挺好用的 不过要注意如果把font放在最后,其他会使用默认值,可能会覆盖掉前面的 例如新学的行高 在font中语法是 font:30px/40px &qu ...

  9. 不可忽视的Dubbo线程池

    问题描述 线上突然出现Dubbo超时调用,时间刚好为Consumer端设置的超时时间. 有好几个不同的接口都报超时了 第1次调用超时,第2次(或第3次)重试调用非常快(正常水平) Dubbo调用超时的 ...

  10. inux 下配置网卡的别名即网卡子IP的配置 转

    what 什么是ip别名?用windows的话说,就是为一个网卡配置多个ip.when 什么场合增加ip别名能派上用场?布网需要.多ip访问测试.特定软件对多ip的需要...and so on. ho ...