Hive UDF<用户自定义函数>入门

一、简介

Hive有三种类型的UDF:(普通)UDF、用户定义聚集函数(user-defined aggregate function,UDAF)以及用户定义表生成函数(user-defined table-generating function,UDTF)。

  • UDF:操作作用于单个数据行,且产生一个数据行作为输出。大多数函数(例如数学函数和字符串函数)都属于这一类。
  • UDAF:接受多个输入数据行,并产生一个输出数据行。比如,COUNT和MAX函数。
  • UDTF:作用于单个数据行,且产生多个数据行(即一个表)作为输出。比如,alteral view与explode函数。

二、编写UDF

在开发 Hive UDF 之前,我们需要引入一个 jar包:hive-exec。

<dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-exec</artifactId>
    <version>2.1.1</version>
    <scope>provided</scope>
 </dependency>

默认的scope是compile,表示项目在编译,测试,运行阶段都需要这个jar包在classpath中。这里指定scope为provided,表示仅在编译,测试阶段需要这个Jar包。因为在运行时,hive已经有该Jar包了,不需要重复依赖。

接着,我们需要实现UDF接口。目前 Hive 的 UDF 主要分为2种类型的接口:UDF和GenericUDF。

  • UDF:是一种比较简单的类,继承的基类为 org.apache.hadoop.hive.ql.exec.UDF
  • GenericUDF:相对复杂一些,主要针对于类型检查等具有更好的控制。继承的基类为 org.apache.hadoop.hive.ql.udf.generic.GenericUDF。

下面,我们看一个简单的UDF实现类:Strip

package com.scb.dss.udf;

import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;

@Description(name = "strip",
        value = "_FUNC_(str) - Removes the leading and trailing space characters from str.")
public class Strip extends UDF {

    // 去除str开头以及结尾的空格
    public String evaluate(String str) {
        if (str == null) {
            return null;
        }
        return StringUtils.strip(str);
    }

    // 去除str开头以及结尾的stripChars中该指定字符集中的任意字符
    public String evaluate(String str, String stripChars) {
        if (str == null) {
            return null;
        }
        return StringUtils.strip(str, stripChars);
    }
}

这个Strip类有两个evaluate方法。第一个方法会去除str开头以及结尾的空格,而第二个方法会去除str开头以及结尾的stripChars中该指定字符集中的任意字符。

@Description 注解注明了关于该UDF函数的文档说明,后续可通过desc function <UDF> 命令查看。该注解有三个属性:name,value,extended。

  • name:表明了该函数的名称
  • value:描述了该函数的作用,其中_FUNC_是个宏定义,在desc时候会被替换为这个函数的实际名称
  • extended:主要用来编写函数使用示例

其他需要注意的点:

  • UDF名称对大小写不敏感
  • Hive支持在UDF中使用Java的基本数据类型(以及java.util.map和java.util.list这样的类型)。
  • Hive也支持Hadoop基本数据类型,比如Text。推荐使用Hadoop基本数据类型,这样可以利用对象重用的优势,增效节支。

下面,做个简单UT

package com.scb.dss.udf;

import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.*;

public class StripTest {
    private Strip strip = new Strip();

    @Test
    public void evaluate() {
        System.out.println(strip.evaluate(" a b c "));
        Assert.assertEquals("a b c", strip.evaluate(" a b c "));
        System.out.println(strip.evaluate(" a b c a", "a"));
        Assert.assertEquals(" a b c ", strip.evaluate(" a b c a", "a"));
        System.out.println(strip.evaluate(" a b c a", "a "));
        Assert.assertEquals("b c", strip.evaluate(" a b c a", "a "));
    }
}

三、部署UDF

1. 打包

mvn clean package

2. 上传Jar包到HDFS

hdfs dfs -put hive-udf.jar /user/hive/

3. 通过beeline连接HIVE

beeline -u jdbc:hive2://host:10000/default -n username -p 'password'

4. 创建函数

create function strip as 'com.scb.dss.udf.UDFStrip' using jar 'hdfs:///user/hive/hive-udf.jar';

5. 使用

通过desc function <UDF> 查看UDF描述信息。

select strip('0a0', '0');  // 去除首位的0

四、其他

  1. 删除函数:drop function <udf>
  2. 创建临时函数:create temporary function <udf> as <udf.class.path>

猜你喜欢

转载自blog.csdn.net/qq_37771475/article/details/121636984