Hive用户自定义函数之UDF开发

在进行大数据分析或者开发的时候,难免用到Hive进行数据查询分析,Hive内置很多函数,但是会有一部分需求需要自己开发,这个时候就需要自定义函数了,Hive的自定义函数开发非常方便,今天首先讲一下UDF的入门开发。

UDF开发

简单实现将字符串小写化的功能。

环境版本

  • Hive 3.1.0.X
  • JDK 8
  • Maven 3.8.1

开发步骤

首先Maven创建

引入Jar包
复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hive.tutorial</groupId>
    <artifactId>low-str</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

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

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>
</project>
编写UDF函数
复制代码
package com.hive.tutorial.udf;

import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
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;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
import org.apache.hadoop.io.Text;

/**
 * @author panlf
 * @date 2024/1/3
 */
public class LowStr extends GenericUDF {

    StringObjectInspector stringObjectInspector;

    @Override
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
        if(arguments == null || arguments.length != 1){
            throw new UDFArgumentException("该方法只接受一个参数");
        }

        ObjectInspector a = arguments[0];

        if (!(a instanceof StringObjectInspector)) {
            throw new UDFArgumentException("该方法的参数必须是字符串");
        }
        //检查通过后,将参数赋值给成员变量ObjectInspector,为了在evaluate()中使用
        this.stringObjectInspector = (StringObjectInspector) a;

        //用工厂类生成用于表示返回值的ObjectInspector
        return PrimitiveObjectInspectorFactory.javaStringObjectInspector;
    }

    @Override
    public Object evaluate(DeferredObject[] arguments) throws HiveException {
        String v = stringObjectInspector.getPrimitiveJavaObject(arguments[0].get());
        return new Text(v.toLowerCase());
    }

    @Override
    public String getDisplayString(String[] children) {
        return "将输入的字符串小写化";
    }
}

注意很多网上资料其实是继承UDF这个类的,但是这个类已过时了,建议使用GenericUDF

GenericUDF和UDF都是Hive中的用户自定义函数,但两者在处理数据类型和灵活性上有所不同。基础的UDF接口适合于简单的数据类型,如文本、整数等,而复杂的GenericUDF则可以处理更复杂的数据类型,包括Map、List和Set。

具体来说,以下是GenericUDF相对于UDF的优势:

  • 处理复杂数据类型:GenericUDF不仅可以处理Hadoop和Hive的基本类型,如Text、IntWritable、LongWritable、DoubleWritable等,还可以处理复杂的数据结构,如Array、Map、Struct等。
  • 灵活性:相比于UDF,GenericUDF提供了更多的灵活性。例如,它可以在函数开始之前和结束之后执行一些初始化和清理操作。此外,GenericUDF允许用户重载evaluate()方法,使其具有更强的功能。

因此,当您需要处理的数据类型比较复杂或需要进行一些特定的初始化和清理操作时,建议使用GenericUDF而不是UDF。

打包
复制代码
mvn clean package

部署到Hive

Jar上传至服务器

首先将Jar传到服务器,我是传到服务器的/data/temp_data/文件夹下

HDFS将Jar传入到Hadoop

通过HDFS命令将Jar包传到Hadoop上

复制代码
> hdfs dfs -put /data/temp_data/low-str-1.0.0.jar /hivejar/hiveudf

Hive客户端操作,添加Jar包

运行Hive cli,进入Hive客户端

运行以下命令

复制代码
 hive > add jar hdfs://172.23.39.9:8020/hivejar/hiveudf/low-str-1.0.0.jar;

建函数

临时函数
复制代码
create temporary function low_str as 'com.hive.tutorial.udf.LowStr'; 

然后即可使用

复制代码
select low_str('AAAA');


注意

Hive的UDF临时函数在会话结束时失效

永久函数
复制代码
create function sys.low_str as 'com.hive.tutorial.udf.LowStr' using jar 'hdfs://172.23.39.9:8020/hivejar/hiveudf/low-str-1.0.0.jar';

注意sys.low_str 中的sys代表的是库名,如果没有指定的话,默认是default

销毁函数
复制代码
drop function low_str;
查看函数
复制代码
//查看全部函数
show functions;

### 查看某个函数
describe function low_str;

Java中使用永久函数

我在Java的程序中调用该永久函数,发生以下错误,就是无法识别出注册的函数。

我通过查资料发现以下方法可解决(包括且不限于)

  • 调用函数的时候,是否带上了库名(我第一次建立在default下面,我在Hive客户端是不带default就能直接使用函数,所以我以为Java程序中也能直接写,但是测试发现Java程序中需要使用default.low_str
  • 使用RELOAD FUNCTIONS,重刷FUNCTIONS信息
  • 重启Hive
    。。。。
相关推荐
B站计算机毕业设计超人40 分钟前
计算机毕业设计Python+百度千问大模型微博舆情分析预测 微博情感分析可视化 大数据毕业设计(源码+LW文档+PPT+讲解)
大数据·hive·hadoop·python·毕业设计·知识图谱·课程设计
王九思8 小时前
大数据查询工具Hive介绍
大数据·hive·hadoop
王九思8 小时前
Hive Hook 机制
数据仓库·hive·hadoop
lipWOFb1 天前
扩展卡尔曼滤波soc估算 基于EKF算法的锂电池SOC 卡尔曼滤波估计电池soc ,simul...
hive
走遍西兰花.jpg1 天前
hive如何使用python脚本
数据仓库·hive·hadoop·python
德彪稳坐倒骑驴1 天前
Hive电商分析项目 Azkaban自动化运行
hive·hadoop·自动化
yumgpkpm1 天前
Cloudera CDP/CMP华为鲲鹏版下 Spark应用加速,华为昇腾芯片的实用配置过程
hive·hadoop·elasticsearch·flink·kafka·hbase·cloudera
沃达德软件1 天前
智慧监管新形态:科技赋能
大数据·数据仓库·人工智能·科技·数据库架构
青云交1 天前
Java 大视界 -- Java+Spark 构建离线数据仓库:分层设计与 ETL 开发实战(445)
java·数据仓库·spark·分层设计·java+spark·离线数据仓库·etl 开发
zgl_200537791 天前
源代码:ZGLanguage 解析SQL数据血缘 之 显示 WITH SQL 结构图
大数据·数据库·数据仓库·sql·数据治理·etl·数据血缘