文章目录
1.简介
- UDF函数分类
- UDF : User-Defined Function 一进一出,eg. substr
- UDAF : User-Defined Aggregation Function 多进一出,eg.
- UDTF : User-Defined Table-Generating Function 一进多出,eg.
2.非源码级别自定义UDF函数
2.1.准备自定义函数
2.1.1.编写函数类
AddPrefixUDF.java
package com.cll.bigdata.hive.udf;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.hadoop.hive.ql.exec.UDF;
/**
* @ClassName AddPrefixUDF
* @Description 添加前缀 udf
* @Author cll
* @Date 2019-09-18 21:58
* @Version 1.0
**/
public class AddPrefixUDF extends UDF {
/**
* 给字符串添加前缀
* @param value 字符串
* @return
*/
public String evaluate(String value){
int num = RandomUtils.nextInt(10);
return num + "_" + value;
}
}
2.1.2.打包上传并至服务器
2.2.注册函数
注册函数分为两种方式:
临时 : 只在当前hive窗口有效,窗口关闭,函数即被移除
永久 : 当前hive窗口关闭,重新打开也可以使用
2.2.1.临时
格式 :CREATE TEMPORARY FUNCTION 函数名(自定义) AS “自定义函数的全路径”;
# 添加jar包
hive (cll_ba)> add jar /home/hadoop/lib/cll-hadoop-1.0.jar;
# 创建临时方法(窗口关闭该函数就会被移除)
hive (cll_ba)> CREATE TEMPORARY FUNCTION add_prefix AS "com.cll.bigdata.hive.udf.AddPrefixUDF";
# 原始数据
hive (cll_ba)> select * from access_log;
OK
access_log.uid access_log.pid
user1 a
user2 b
user3 c
user1 b
user3 a
user3 c
user2 c
user1 a
user1 c
# 使用函数 可以看出 uid的值前面已经拼接了随机数
hive (cll_ba)> select add_prefix(uid),pid from access_log;
OK
_c0 pid
0_user1 a
8_user2 b
4_user3 c
2_user1 b
5_user3 a
7_user3 c
7_user2 c
6_user1 a
7_user1 c
Time taken: 0.142 seconds, Fetched: 9 row(s)
2.2.2.永久
需要先把jar包上传至hdfs
格式 :CREATE FUNCTION 函数名(自定义) AS “自定义函数的全路径” USING JAR “jar包的hdfs路径”;
hive (cll_ba)> CREATE FUNCTION add_prefix AS "com.cll.bigdata.hive.udf.AddPrefixUDF"
> USING JAR "hdfs://hadoop000:9000/hadoop/jar/cll-hadoop-1.0.jar";
converting to local hdfs://hadoop000:9000/hadoop/jar/cll-hadoop-1.0.jar
Added [/tmp/71a20550-93e2-435a-a4c3-438a5d29678b_resources/cll-hadoop-1.0.jar] to class path
Added resources: [hdfs://hadoop000:9000/hadoop/jar/cll-hadoop-1.0.jar]
OK
Time taken: 0.294 seconds
hive (cll_ba)> select add_prefix(uid),pid from access_log;
OK
_c0 pid
2_user1 a
0_user2 b
1_user3 c
8_user1 b
8_user3 a
1_user3 c
0_user2 c
1_user1 a
9_user1 c
Time taken: 0.35 seconds, Fetched: 9 row(s)
3.源码级别自定义UDF函数
说明:改动hive源码,需要重新编译源码并部署
- 添加自定义函数
新增 UDFAddPrefix.java
package org.apache.hadoop.hive.ql.udf;
import org.apache.commons.lang.math.RandomUtils;
import org.apache.hadoop.hive.ql.exec.UDF;
/**
* @ClassName UDFAddPrefix
* @Description 添加前缀
* @Author cll
* @Date 2019-09-27 14:02
* @Version 1.0
**/
public class UDFAddPrefix extends UDF {
public String evaluate(String fieldValue){
int randomNum = RandomUtils.nextInt(5);
return randomNum + "_" + fieldValue;
}
}
修改:org.apache.hadoop.hive.ql.exec.FunctionRegistry.java
⚠️ 如果直接是在linux上面修改的源码,切记别忘了手动import UDFAddPrefix
static {
system.registerUDF("add_prefix_new", UDFAddPrefix.class, false);
}
- 编译
mvn clean package -DskipTests -Phadoop-2 -Pdist
- 配置
1.拷贝一份conf下面的hive-env.sh.template hive-env.sh 并修改hadoop_home配置
# Set HADOOP_HOME to point to a specific hadoop install directory
HADOOP_HOME=/home/hadoop/app/hadoop
2.新增一个hive-site.sh
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- JDBC URL -->
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost:3306/hive_compile_metadata?createDatabaseIfNotExist=true&characterEncoding=UTF-8&useSSL=false</value>
</property>
<!-- JDBC DRIVER -->
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<!-- JDBC USERNAME -->
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<!-- JDBC PASSWORD -->
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<!-- Hive命令行显示当前数据库名 -->
<property>
<name>hive.cli.print.current.db</name>
<value>true</value>
</property>
<!-- Hive命令行显示列名 -->
<property>
<name>hive.cli.print.header</name>
<value>true</value>
</property>
</configuration>
- 配置环境变量
## hive
export HIVE_HOME=/home/hadoop/app/hive
export PATH=$HIVE_HOME/bin:$PATH
- 启动
# 启动
[hadoop@hadoop000 hive-compile]$ hive
# 查看函数 已经出现了自定义的函数
hive> show functions;
OK
...
add_prefix_new
...
- 测试自定义函数
# 建库
hive> create database cll_ba;
hive> use cll_ba;
# 建表
create table access_log(
uid string,
pid string
) row format delimited fields terminated by '\t';
# 准备测试数据
[hadoop@hadoop000 data]$ vi access_log.txt
user1 a
user2 b
user3 c
user1 b
user3 a
user3 c
user2 c
user1 a
user1 c
# 加载数据
hive> LOAD DATA LOCAL INPATH '/home/hadoop/data/access_log.txt' into table cll_ba.access_log;
# 测试函数
hive> select add_prefix_new(uid) from access_log;
OK
1_user1
3_user2
3_user3
2_user1
3_user3
3_user3
3_user2
0_user1
3_user1
Time taken: 0.098 seconds, Fetched: 9 row(s)
完成!