文章目录

  • Hive自定义标准函数(UDF)
  • 继承UDF类或GenericUDF类
  • 添加依赖包
  • 继承UDF类
  • 重写evaluate()方法并实现函数逻辑
  • 打包为jar文件编译
  • 复制到正确的HDFS路径
  • 使用jar创建临时/永久函数
  • 创建临时函数并调用
  • 创建永久函数并调用
  • 总结


Hive自定义标准函数(UDF)

继承UDF类或GenericUDF类

添加依赖包

利用maven添加对应的依赖包,因网络原因,有可能会出现添加不成功的情况,可以将对应的jar包文件夹删除后重写下载,或者更换国内的下载镜像,或者直接从别人哪里拷贝对应的jar,都可以解决依赖包标红的问题

<dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-common</artifactId>
      <version>2.6.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.hive</groupId>
      <artifactId>hive-exec</artifactId>
      <version>1.1.0</version>
    </dependency>

继承UDF类

public class TimeDiff extends UDF {
}

重写evaluate()方法并实现函数逻辑

可以利用@Description的方式添加注释,这样打完jar包之后,在hive内可以对应查看到注释内容,常规的注释只能在java环境内才能看到,hive只能用@Description的方式才可以

@Description(
        name = "timeDiff",
        value = "_FUNC_(dataStr,dataStr,diffType) -"+
                "diffType:0:date;1:hour;2:minute;3:second;"+
                "4:year;5:month"+"result:"+
                "while 0 is date_diff ...",
        extended = "select timeDiff('2021-04-06 12:00:00','2021-04-05 23:00:00',1);"+
                "result is '13 hour'"
)
public class TimeDiff extends UDF {
    public Text evaluate(Text dataStr1, Text dataStr2, IntWritable diffType) throws ParseException {
        String s1 = dataStr1.toString();
        String s2 = dataStr2.toString();
        int type = diffType.get();
        //把字符串转成date型
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d1 = sdf.parse(s1);
        Date d2 =sdf.parse(s2);
        long diff = Math.abs(d1.getTime() - d2.getTime());
        long result=0;
        String dateType="";
        switch (type){
            case 0:result=diff/1000/3600/24;
            dateType="day";
                break;
            case 1:result=diff/1000/3600;
            dateType="hour";
                break;
            case 2:result=diff/1000/60;
                dateType="minute";
                break;
            case 3:result=diff/1000;
                dateType="second";
                break;
            case 4:result=diff/1000/3600/24/365;
                dateType="year";
                break;
            case 5:result=diff/1000/3600/24/30;
            dateType="month";
                break;
        }
        return new Text(result+"  "+dateType);
    }
}

打包为jar文件编译

打jar包的方式跟以往的方式有所不同,需要在Terminal 内输入mvn clean 命令先清空文件,然后再用 mvn install 命令来生成jar包

hive计算两个字符串时间差 hive 计算时间差_hive计算两个字符串时间差

hive计算两个字符串时间差 hive 计算时间差_jar_02


提示build success 之后 表示jar包生成成功

hive计算两个字符串时间差 hive 计算时间差_hive_03


在taeget内可以找到对应的jar包文件,找到后上传到linux系统内,供hive使用

hive计算两个字符串时间差 hive 计算时间差_jar_04

复制到正确的HDFS路径

在hdfs内新建一个文件夹用来存放jar包,并且把刚上传到linux系统内的jar包再次上传到hdfs刚刚新建的文件夹内

hdfs dfs -mkdir /jars/
hdfs dfs -put /hivedata/20210406-hiveudf-1.0-SNAPSHOT.jar /jars/

使用jar创建临时/永久函数

创建临时函数并调用

将jar包上传到linux系统内,就可以直接创建临时函数了,临时函数一旦退出hive则失效,本次测试的功能为将小写转为大写
hive环境下输入命令:

hive> add jar /hivedata/20210406-hiveudf-1.0-SNAPSHOT.jar;                --加载jar包
Added [/hivedata/20210406-hiveudf-1.0-SNAPSHOT.jar] to class path
Added resources: [/hivedata/20210406-hiveudf-1.0-SNAPSHOT.jar]
hive> list jars;                                                       --查看已加载的jar包
/hivedata/20210406-hiveudf-1.0-SNAPSHOT.jar
hive> create temporary function upstr as 'cn.kgc.kb11.TestUpper';          --创建临时函数
OK
Time taken: 0.005 seconds
hive> select upstr('abcdsgsdfgdfgsdfgsdga');                              --调用临时函数
OK
_c0
ABCDSGSDFGDFGSDFGSDGA
Time taken: 0.036 seconds, Fetched: 1 row(s)

创建永久函数并调用

永久函数的调用依赖于hdfs上面的jar包,只要hdfs上对应路径的jar包文件一直存在,则函数就不会失效,下面介绍使用方法

hive> create function timeDiff as 'cn.kgc.kb11.udf.TimeDiff'
    > using jar 'hdfs:///jars/20210406-hiveudf-1.0-SNAPSHOT.jar';             --根据hdfs上面的路径加载jar包
converting to local hdfs:///jars/20210406-hiveudf-1.0-SNAPSHOT.jar
Added [/tmp/5fafde50-5795-468a-a089-2501576d6c57_resources/20210406-hiveudf-1.0-SNAPSHOT.jar] to class path
Added resources: [hdfs:///jars/20210406-hiveudf-1.0-SNAPSHOT.jar]
OK
Time taken: 0.139 seconds
hive> desc function timeDiff;                      --查询jar包内的注释内容
OK
tab_name
timeDiff(dataStr,dataStr,diffType) -diffType:0:date;1:hour;2:minute;3:second;4:year;5:monthresult:while 0 is date_diff ...
Time taken: 0.1 seconds, Fetched: 1 row(s)
hive> desc function extended timeDiff;                 --查询jar包内注释内容中的extended内容
OK
tab_name
timeDiff(dataStr,dataStr,diffType) -diffType:0:date;1:hour;2:minute;3:second;4:year;5:monthresult:while 0 is date_diff ...
Synonyms: emp.timediff
select timeDiff('2021-04-06 12:00:00','2021-04-05 23:00:00',1);result is '13 hour'
Time taken: 0.006 seconds, Fetched: 3 row(s)
hive> select timeDiff("2021-04-06 12:56:33","2023-05-06 11:24:22",1);           --调用函数计算时间差
OK
_c0
18238  hour
Time taken: 0.27 seconds, Fetched: 1 row(s)

总结

UDF函数其实就是一个简单的函数,执行过程就是在Hive转换成mapreduce程序后,执行java方法,类似于像Mapreduce执行过程中加入一个插件,方便扩展. UDF只能实现一进一出的操作,如果需要实现多进一出,则需要实现UDAF .

Hive可以允许用户编写自己定义的函数UDF,来在查询中使用。