五、Hive数据仓库应用之Hive函数(二)(超详细步骤指导操作,WIN10,VMware Workstation 15.5 PRO,CentOS-6.7)

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.

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七层楼的疯子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值