Hive 内置了很多函数,但是有些特殊场景下是没有办法满足的。可以使用基于Java的用户定义函数(UDF)扩展配置单元SQL,并从配置单元查询调用UDF。


用Java实现Hive的UDF非常简单,只需要编写Java代码,打包成JAR包,最后在Hive中注册就可以使用。


本文演示如何创建一个Hive UDF,以及如何注册使用。


Java编写Hive的UDF代码很简单,只需要做两件事:

  • 第一,继承UDF类。
  • 第二,实现evaluate( )方法。


1、准备环境


首先准备开发环境

  • JDK 8
  • Apache Maven 3.3.9
  • IntelliJ IDEA


创建一个 Maven 项目,File > New > Project > Maven,点击 Enable Auto-Import,修改pom.xml文件如下:


<?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.data.hive</groupId>
    <artifactId>hive_udf</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF8</project.build.sourceEncoding>
        <hadoop.version>2.7.2</hadoop.version>
        <hive.version>2.0.1</hive.version>
    </properties>

    <repositories>
        <!--加入Hadoop原生态的maven仓库的地址-->
        <repository>
            <id>Apache Hadoop</id>
            <name>Apache Hadoop</name>
            <url>https://repo1.maven.org/maven2/</url>
        </repository>
    </repositories>

    <dependencies>
        <!--添加hadoop依赖-->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <!--添加hive依赖-->
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-exec</artifactId>
            <version>${hive.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <filters>
                                <filter>
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass></mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>




2、编写代码


这里是一个 Hive UDF,它使用一个长参数并返回其十六进制表示。


package com.cuteximi.udf
import org.apache.hadoop.hive.ql.exec.UDF
import org.apache.hadoop.io.LongWritable

// This UDF takes a long integer and converts it to a hexadecimal string.

class ToHex extends UDF {
  def evaluate(n: LongWritable): String = {
    Option(n)
    .map { num =>
        // Use Scala string interpolation. It's the easiest way, and it's
        // type-safe, unlike String.format().
        f"0x${num.get}%x"
    }
    .getOrElse("")
  }
}


打包代码。

3、部署


官方提供了两种部署 UDF 的方式:


  • 临时部署(Temporary Functions)
  • 永久部署(Permanent Functions)


两者的区别在于:临时部署的方式,只会在当前 Session 下有效并可用;永久部署的方式,在部署成功后任何一个 Hive 客户端(重新启动的 Hive 客户端,已经启动的客户端需要重新加载)都可以使用。


(1) 临时部署


这个是最常见的 Hive 使用方式,通过 hive 命令来完成 UDF 的部署;

hive> add jar /path/to/local.jar;
hive> create temporary function to_hex as 'com.cuteximi.udf.ToHex';


(2) 永久部署


这种方式是 hive-0.13 版本以后开始支持的注册方法;


hive> create function to_hex
hive> as 'com.cuteximi.udf.ToHex'
hive> using jar 'hdfs:///path/to/hdfs.jar';


需要注意两点:1 如果方法前面不指定数据库,会默认创建在当前数据库里面。


在一个配CLI会话中创建永久函数可能不会反映在配置单元server2或其他配置单元CLI会话中(如果它们是在创建函数之前启动的)。


在HiveServer2或HiveCLI会话中发出RELOAD函数将允许它获取对永久函数的任何更改,这些更改可能是由不同的HiveCLI会话完成的。由于向后兼容的原因,重新加载函数;具体见讨论:HIVE-2573




4、常用命令

-- 查看所有函数(内置函数+自定义函数)
show functions;
-- 查看某个函数的使用说明
describe function function_name;
-- 创建临时自定义函数
create temporary function function_name as class_name;
-- 删除临时自定义函数
drop temporary function [if exists] function_name;
-- 创建永久自定义函数
create function [db_name.]function_name as class_name
  [using jar|file|archive 'file_uri' [, jar|file|archive 'file_uri'] ];
-- 删除永久自定义函数
drop function [if exists] function_name;
-- 重载函数
reload function;



5、参考



(完)