一、内置函数
# 查看hive内置函数
show functions;
# 查看函数描述信息
desc function max;
二、用户自定义函数UDF
1. 用户定义函数-UDF
User Defined Function
操作作用于单个数据行,并且产生一个数据行作为输出。大多数函数都属于这一类(比如数学函数和字符串函数)。
简单来说:
UDF:返回对应值,一对一
# 0. 导入hive依赖
<dependencies>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>3.1.2</version>
</dependency>
</dependencies>
# 1.定义一个类继承UDF
1. 必须继承UDF
2. 方法名必须是evaluate
package function;
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
public class HelloUDF extends UDF {
// 方法名必须叫evaluate
public String evaluate(String s1){
return "你好,"+s1;
}
}
# 2. 配置maven打包环境,打包jar
<properties>
<!--解决编码的GBK的问题-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<finalName>funcHello</finalName>
</build>
# 打包
mvn package
# 3. 上传linux,导入到函数库中。
# 在hive命令中执行
add jar /opt/data/funcHello.jar; # hive session级别的添加,
delete jar /opt/data/funcHello.jar; # 如果重写,记得删除。
create temporary function hello as "function.HelloUDF"; # temporary是会话级别。
# 删除导入的函数
drop temporary function hello;
# 4. 查看函数并使用函数
-- 1. 查看函数
desc function hello;
-- 2. 使用函数进行查询
select hello(name) from t_person;
2. 用户自定义函数-UDTF
User Defined Table Function
操作作用于一个或多个输入数据行,并生成一个或多个数据行作为输出。与大多数函数不同,UDTF 可以生成多行数据,通常用于需要生成表格形式结果的场景。
简单来说:
UDTF:一对多
自定义一个 UDTF 实现将一个任意分割符的字符串切割成独立的单词。
create table t_person3(
name string,
hobbies string
);
insert into t_person3 values ('张三','抽烟-喝酒-烫头'),('李四','唱-跳-rap');
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import java.util.ArrayList;
import java.util.List;
public class MyUDTF extends GenericUDTF {
private ArrayList<String> outList = new ArrayList<String>();
@Override
public StructObjectInspector initialize(StructObjectInspector argOIs) throws UDFArgumentException {
//1.定义输出数据的列名和类型
List<String> fieldNames = new ArrayList<String>();
List<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();
//2.添加输出数据的列名和类型
fieldNames.add("lineToWord");
fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
}
@Override
public void process(Object[] args) throws HiveException {
//1.获取原始数据
String arg = args[0].toString();
//2.获取数据传入的第二个参数,此处为分隔符
String splitKey = args[1].toString();
//3.将原始数据按照传入的分隔符进行切分
String[] fields = arg.split(splitKey);
//4.遍历切分后的结果,并写出
for (String field : fields) {
//集合为复用的,首先清空集合
outList.clear();
//将每一个单词添加至集合
outList.add(field);
//将集合内容写出
forward(outList);
}
}
@Override
public void close() throws HiveException {
}
}
测试方式同自定义UDF:打包、添加jar、创建函数...
add jar xxxxx.jar;
create temporary function myexplode as "function.MyUDTF";
select name,hobby from t_person3 lateral view myexplode(hobbies,'-') t1 as hobby;
三、永久函数和临时函数
临时函数和永久函数的区别:临时函数仅对当前session(黑窗口)有效。永久函数是全局的。
1. 临时函数
1.1 添加jar包的两种方法
方法一: add jar /home/hadoop/lib/hive-1.0-SNAPSHOT.jar;
方法二: 在hive的文件夹下面创建auxlib文件夹,将jar包上传到auxlib文件夹下面,重启hive。
1.2 创建临时函数
语法:CREATE TEMPORARY FUNCTION function_name AS class_name;
function_name函数名
class_name 类路径,包名+类名
1.3 删除临时函数
语法:DROP TEMPORARY FUNCTION [IF EXISTS] function_name;
2. 永久函数
2.1 在HDFS上创建hivelib目录,将jar包上传到HDFS的hivelib目录下
hdfs dfs -mkidr /hivelib
hdfs dfs -put funcHello.jar /hive/lib
2.1 创建永久函数的语法:
CREATE FUNCTION [db_name.]function_name AS 'class_name' USING JAR 'hdfs路径/hivelib/funcHello.jar'
drop function function_name
四、总结
定义单行函数,通过继承UDF,重写evaluate方法;
定义炸裂函数,通过继承GenericUDTF,重写process方法;
将项目打成jar包(mvn clean package),上传到linux服务器,如果是定义永久函数需要上传到HDFS;
通过create function 函数名的方式创建函数即可。
应用场景:
单行函数生成随机数,函数的参数是生成随机数的最大值,例如: 函数名(10),作用是生成1-10的随机数。
表中存储用户开会员的开始时间和结束时间,统计每个月的会员人数。通过自定义炸裂函数将一个用户开启会员的时间进行炸裂,得到用户,会员月份。例如 1001 2022-09-05 2023-09-05。生成炸裂结果就是 1001 2022-09、 1001 2022-10、...