Hive 内置了很多函数,但是有些特殊场景下是没有办法满足的。可以使用基于Java的用户定义函数(UDF)扩展配置单元SQL,并从配置单元查询调用UDF。
用Java实现Hive的UDF非常简单,只需要编写Java代码,打包成JAR包,最后在Hive中注册就可以使用。
本文演示如何创建一个Hive UDF,以及如何注册使用。
Java编写Hive的UDF代码很简单,只需要做两件事:
- 第一,继承UDF类。
- 第二,实现evaluate( )方法。
UDF实现的功能在evaluate里实现。Hive根据类名来创建UDF,调用的时候根据evaluate参数来调用不同的方法,实现不同的功能。
准备环境
首先准备开发环境
- 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>
编写代码
这里是一个 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("")
}
}
部署
官方提供了两种部署 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
常用命令
-- 查看所有函数(内置函数+自定义函数)
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;
参考
- https://kb.databricks.com/data/hive-udf.html
- https://snowplowanalytics.com/blog/2013/02/08/writing-hive-udfs-and-serdes/
- https://cwiki.apache.org/confluence/display/Hive/HivePlugins
- https://docs.cloudera.com/documentation/enterprise/latest/topics/cm_mc_hive_udf.html
- https://github.com/bmc/spark-hive-udf
- https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateFunction