Hive远程模式部署参考:
一、Hive数据仓库应用之Hive部署(超详细步骤指导操作,WIN10,VMware Workstation 15.5 PRO,CentOS-6.7)
Hive函数参考:
五、Hive数据仓库应用之Hive函数(一)(超详细步骤指导操作,WIN10,VMware Workstation 15.5 PRO,CentOS-6.7)
二、Hive自定义函数
1、UDF(用户自定义函数):
1.1 打开eclipse,选择新建一个Maven项目,配置Maven项目的组织名(GroupId)和项目工程名(ArtifactId),分别设置为“cn.itcast”和“HIveFunction”。
1.2 项目中的XML文件pom.xml用于管理Maven项目依赖的配置文件,本项目需要在配置文件pom.xml中添加用于开发Hive程序的依赖。其中添加的依赖需要与Hive版本对应。
<dependencies>
<!-- Hive依赖-->
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
之后点击保存即可,需要等待后台自动下载相关依赖包,界面右下角可查看下载进度,中间不要停止,否则会导致报错。
1.3 选中并右击项目HiveFunction 中的“java”目录,在弹出的菜单栏中依次选择“New→Package”,从而新建Package包,将名称命名为cn.itcast.hive。
1.4 选中包“cn.itcast.hive”并单击鼠标右键,在弹出的菜单中依次选择“New→Java Class”新建Java类,将Java类命名为hiveUDF。
1.5 编写UDF类,在类hiveUDF中实现比较两列数值是否相等,具体内容如下。
package cn.itcast.hive;
import org.apache.hadoop.hive.ql.exec.UDF;
public class hiveUDF extends UDF {
public String evaluate(int col1,float col2){
if (col1>col2){
return "max:"+col1+",diffe:"+(col1-col2);
}else if(col1<col2){
return "max:"+col2+",diffe:"+(col2-col1);
}else {
return "0";
}
}
}
1.6 右键点击新建的UDF类,选择“Export→JAR file”封装导出jar包,之后勾选需要导出的“hiveUDF”类文件,设置jar包导出位置, 封装的jar包名称为“hive_UDF.jar”。
1.7 在虚拟机node-01中创建目录/export/jar/,在目录/export/jar/中执行“rz”命令,将hive_UDF.jar上传到虚拟机node-01目录/export/jar/下。
mkdir -p /export/jar/
cd /export/jar/
1.8 在虚拟机node-02中使用Hive客户端工具Beeline,远程连接虚拟机node-01的HiveServer2服务操作Hive,将虚拟机node-01中目录/export/jar/下的hive_UDF.jar添加到Hive中。之后执行“LIST JARS;”命令,查看当前Hive中包含的jar包。
ADD JAR /export/jar/hive_UDF.jar;
LIST JARS;
1.9 在Hive客户端工具Beeline中,创建临时函数CompareSize。执行“SHOW FUNCTIONS LIKE 'Com*';
”命令,查看创建的函数CompareSize,若不指定子句LIKE,则会查询Hive的所有函数包括内置函数。
CREATE TEMPORARY FUNCTION CompareSize AS 'cn.itcast.hive.hiveUDF';
SHOW FUNCTIONS LIKE 'Com*';
1.10 使用函数CompareSize,比较员工信息表employess_table中列employess_table和staff_age的值,命令如下。
SELECT CompareSize(staff_age,late_deduction) FROM hive_database.employess_table;
2、UDTF(用户自定表生成函数):
2.1 UDTF(用户自定表生成函数)的创建、封装、上传过程和UDF(用户自定义函数)完全一致,在上个实验创建的Maven工程的基础上进行类文件的新建即可,无需再次添加依赖信息。
主要区别是创建的java类文件名称为“hiveUDTF”,封装的jar包名称为“hive_UDTF.jar”类文件的具体内容如下:
public class hiveUDTF extends GenericUDTF {
private PrimitiveObjectInspector stringOI = null;
@Override
public StructObjectInspector initialize(ObjectInspector[] args)
throws UDFArgumentException {
if (args.length != 1){
throw new UDFArgumentLengthException(
"hiveUDTF() takes only one argument");
}
if (args[0].getCategory() !=
ObjectInspector.Category.PRIMITIVE
&& ((PrimitiveObjectInspector) args[0])
.getPrimitiveCategory()
!= PrimitiveObjectInspector
.PrimitiveCategory.STRING) {
throw new UDFArgumentException(
"hiveUDTF() takes a string as a parameter");
}
stringOI = (PrimitiveObjectInspector) args[0];
List<String> fieldNames = new ArrayList<String>(2);
List<ObjectInspector> fieldOIs =
new ArrayList<ObjectInspector>(2);
fieldNames.add("last_name");
fieldNames.add("first_name");
fieldOIs.add(
PrimitiveObjectInspectorFactory
.javaStringObjectInspector);
fieldOIs.add(
PrimitiveObjectInspectorFactory
.javaStringObjectInspector);
return ObjectInspectorFactory
.getStandardStructObjectInspector(fieldNames, fieldOIs);
}
public void process(Object[] objects) throws HiveException {
ArrayList<Object[]> result = new ArrayList<Object[]>();
final String name =
stringOI.getPrimitiveJavaObject(objects[0]).toString();
if (name == null || name.isEmpty()) {
result = null;
}
String[] tokens = name.split("\\s+");
result.add(new Object[] { tokens[0], tokens[1] });
Iterator<Object[]> it = result.iterator();
while (it.hasNext()){
Object[] r = it.next();
forward(r);
}
}
public void close() throws HiveException {
}
}
2.2 在虚拟机node-02中使用Hive客户端工具Beeline,远程连接虚拟机node-01的HiveServer2服务操作Hive,将虚拟机node-01中目录/export/jar/下的hive_UDTF.jar添加到Hive中。之后执行“LIST JARS;”命令,查看当前Hive中包含的jar包。
ADD JAR /export/jar/hive_UDTF.jar;
LIST JARS;
2.3 创建临时函数spiltname。执行SHOW FUNCTIONS LIKE 'spilt*'命令,查看创建的函数spiltname,若不指定子句LIKE,则会查询Hive的所有函数包括内置函数。
CREATE TEMPORARY FUNCTION spiltname AS 'cn.itcast.hive.hiveUDTF';
SHOW FUNCTIONS LIKE 'spilt*';
2.4 使用函数spiltname,将员工信息表employess_table中员工姓名拆分为两列。
SELECT spiltname(staff_name) FROM hive_database.employess_table;
3、UDAF(用户自定聚合函数):
3.1 UDAF(用户自定聚合函数)的创建、封装、上传过程和UDF(用户自定义函数)完全一致,在上个实验创建的Maven工程的基础上进行类文件的新建即可,无需再次添加依赖信息。
主要区别是创建的java类文件有两个,名称分别为“hiveUDAFCollect”和“hiveUDAFMain”,封装jar包时需要将这两个类文件进行封装,同时jar包名称为“hive_UDAF.jar”。两个类文件具体内容见提供的文件“hiveUDAFCollect.java”和“hiveUDAFMain.java”。
hiveUDAFCollect.java:
public class hiveUDAFCollect extends AbstractGenericUDAFResolver {
@Override
public GenericUDAFEvaluator getEvaluator(TypeInfo[] parameters)
throws SemanticException {
//在使用函数时只能指定一个参数
if(parameters.length != 1) {
throw new UDFArgumentTypeException(
parameters.length - 1,
"Exactly one argument is expected.");
}
//判断参数的数据类型是否为Hive的基本数据类型
if(parameters[0].getCategory() !=
ObjectInspector.Category.PRIMITIVE) {
throw new UDFArgumentTypeException(0,
"Pnly primitive type arguments are accepted but "
+ parameters[0].getTypeName()
+ " was passed as parameter 1.");
}
return new hiveUDAFMain();
}
}
hiveUDAFMain.java:
public class hiveUDAFMain extends GenericUDAFEvaluator {
private PrimitiveObjectInspector inputOI;
private StandardListObjectInspector loi;
private StandardListObjectInspector internalMergeOI;
//初始化UDAF
@Override
public ObjectInspector init(Mode m, ObjectInspector[] parameters)
throws HiveException {
super.init(m, parameters);
if(m == Mode.PARTIAL1) {
inputOI = (PrimitiveObjectInspector) parameters[0];
return ObjectInspectorFactory
.getStandardListObjectInspector(
(PrimitiveObjectInspector) ObjectInspectorUtils
.getStandardObjectInspector(inputOI));
}else {
if(!(parameters[0] instanceof StandardListObjectInspector)) {
inputOI = (PrimitiveObjectInspector)
ObjectInspectorUtils
.getStandardObjectInspector(parameters[0]);
return (StandardListObjectInspector)
ObjectInspectorFactory
.getStandardListObjectInspector(inputOI);
}else {
internalMergeOI
= (StandardListObjectInspector) parameters[0];
inputOI = (PrimitiveObjectInspector) internalMergeOI
.getListElementObjectInspector();
loi = (StandardListObjectInspector) ObjectInspectorUtils
.getStandardObjectInspector(internalMergeOI);
return loi;
}
}
}
//定义一个buffer类型的静态类MkArrayAggregationBuffer,用于存储聚合结果
static class MkArrayAggregationBuffer implements AggregationBuffer{
List<Object> container;
}
//返回用于存储中间结果的对象
@Override
public AggregationBuffer getNewAggregationBuffer()
throws HiveException {
MkArrayAggregationBuffer ret = new MkArrayAggregationBuffer();
reset(ret);
return ret;
}
//中间结果返回完成后,重置聚合
@Override
public void reset(AggregationBuffer agg) throws HiveException {
((MkArrayAggregationBuffer) agg).container
= new ArrayList<Object>();
}
//将一行新的数据载入到buffer中
@Override
public void iterate(AggregationBuffer agg, Object[] parameters)
throws HiveException {
assert(parameters.length == 1);
Object p = parameters[0];
if(p != null) {
MkArrayAggregationBuffer myagg
= (MkArrayAggregationBuffer) agg;
putInfoList(p, myagg);
}
}
//将一行新的数据载入到buffer中的具体实现,真正操作数据的部分。
//将数据添加到静态类MkArrayAggregationBuffer的集合container中。
private void putInfoList(Object p, MkArrayAggregationBuffer myagg) {
Object pCopy = ObjectInspectorUtils
.copyToStandardObject(p, this.inputOI);
myagg.container.add(pCopy);
}
//以一种持久化的方式返回当前聚合的内容
@Override
public Object terminatePartial(AggregationBuffer agg)
throws HiveException {
MkArrayAggregationBuffer myagg = (MkArrayAggregationBuffer) agg;
ArrayList<Object> ret = new ArrayList<Object>(myagg.container.size());
ret.addAll(myagg.container);
return ret;
}
//将terminatePartial()方法中聚合的内容合并到当前聚合中
@Override
public void merge(AggregationBuffer agg, Object partial)
throws HiveException {
MkArrayAggregationBuffer myagg = (MkArrayAggregationBuffer) agg;
ArrayList<Object> partialResult =
(ArrayList<Object>) internalMergeOI.getList(partial);
for(Object i : partialResult) {
putInfoList(i, myagg);
}
}
//返回最终聚合结果作为Hive的输出
@Override
public Object terminate(AggregationBuffer agg) throws HiveException {
MkArrayAggregationBuffer myagg = (MkArrayAggregationBuffer) agg;
ArrayList<Object> ret
= new ArrayList<Object>(myagg.container.size());
ret.addAll(myagg.container);
return ret;
}
}
3.2 在虚拟机node-02中使用Hive客户端工具Beeline,远程连接虚拟机node-01的HiveServer2服务操作Hive,将虚拟机node-01中目录/export/jar/下的hive_UDAF.jar添加到Hive中。
添加jar包并创建:
ADD JAR /export/jar/hive_UDAF.jar;
3.3 创建临时函数collectstr。执行SHOW FUNCTIONS LIKE ’ collect *'命令,查看创建的函数collectstr,若不指定子句LIKE,则会查询Hive的所有函数包括内置函数。
CREATE TEMPORARY FUNCTION collectstr AS 'cn.itcast.hive.hiveUDAFCollect';
SHOW FUNCTIONS LIKE 'collect*';
3.4 使用函数collectstr,将学生成绩表student_exam_table中所有学生姓名合并到一
行数据中。
SELECT collectstr(student_name) from hive_database.student_exam_table;
参考文献:黑马程序员.Hive数据仓库应用[M].北京:清华大学出版社,2021.