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.udfimport org.apache.hadoop.hive.ql.exec.UDFimport 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_hexhive> 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
