Hive自定义函数——简单使用

news2024/9/20 14:37:31

        在 Hadoop 生态系统中,特别是在 Hive 和其他 SQL-on-Hadoop 工具中,UDF(用户自定义函数),UDAF(用户自定义聚合函数),以及 UDTF(用户自定义表生成函数)允许用户定义自定义的函数逻辑,以适应特定的业务需求。这些自定义函数帮助扩展 Hive 的功能,在数据处理和分析中变得非常灵活。下面分别介绍这三种函数及其优劣势、适用场景,并给出具体的示例。

1. UDF(User Defined Function) - 用户自定义函数

定义

UDF 是一种用户自定义的单行函数,它将输入的一行数据进行处理并返回一个结果。例如,可以将 UDF 用来执行列的转换或简单的计算。

优势
  • 简单、灵活:UDF 通常处理单行输入并返回单个结果,非常适合执行简单的列级别的操作。
  • 易于实现:编写和注册 UDF 相对容易,只需实现一个特定的方法。
  • 性能较好:因为它只对单行数据操作,所以性能通常较好。
劣势
  • 只能处理一行数据,无法聚合多行数据。
  • UDF 的逻辑相对简单,不能实现复杂的表操作或数据拆分。
适用场景
  • 适用于单列或多列的简单数据转换或处理。
  • 常用于数据清洗、格式化、字符串处理等场景。
示例

假设需要一个 UDF 函数来将字符串转为大写:

public class UpperCaseUDF extends UDF {
    public String evaluate(String input) {
        return input == null ? null : input.toUpperCase();
    }
}

使用场景:

SELECT UPPERCASE(name) FROM employees;

将 employees 表中的 name 列转为大写。

2. UDAF(User Defined Aggregation Function) - 用户自定义聚合函数

定义

UDAF 是一种用户自定义的聚合函数,它处理多行数据,并返回一个聚合后的结果。类似于 SQL 中的 SUMAVG 等聚合函数。

优势
  • 能够聚合多行数据,适合处理需要计算汇总值、平均值、最大值、最小值等操作的场景。
  • 提供了灵活的多行数据处理能力,可以自定义复杂的聚合逻辑。
劣势
  • 实现较为复杂:相比 UDF,编写 UDAF 需要更多的步骤和逻辑处理,如分阶段的聚合和合并操作。
  • 聚合操作需要在不同阶段维护状态,因此可能会消耗更多内存和计算资源。
适用场景
  • 适合需要聚合多行数据的场景,如汇总计算、求平均、最大最小值等。
  • 适用于自定义复杂的统计分析,如百分位数、标准差等。
示例

假设需要计算员工工资的方差,可以编写一个自定义 UDAF。

import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFParameterInfo;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFParameterInfoBase;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFParameterInfoImpl;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory.PrimitiveDoubleObjectInspector;
import org.apache.hadoop.io.DoubleWritable;

public class VarianceUDAF extends AbstractGenericUDAFResolver {

    @Override
    public GenericUDAFEvaluator getEvaluator(GenericUDAFParameterInfo info) throws HiveException {
        return new VarianceEvaluator();
    }

    public static class VarianceEvaluator extends GenericUDAFEvaluator {

        // 聚合状态类,用来保存聚合过程中间结果
        public static class VarianceBuffer implements UDAFEvaluator {
            private long count;      // 数据点个数
            private double sum;      // 数据和
            private double sumOfSquares; // 数据平方和

            public VarianceBuffer() {
                init();
            }

            public void init() {
                count = 0;
                sum = 0.0;
                sumOfSquares = 0.0;
            }
        }

        private PrimitiveDoubleObjectInspector inputOI;
        private ObjectInspector outputOI;

        @Override
        public ObjectInspector init(Mode m, ObjectInspector[] parameters) throws HiveException {
            super.init(m, parameters);

            // 定义输入和输出的 ObjectInspector
            if (m == Mode.PARTIAL1 || m == Mode.COMPLETE) {
                inputOI = (PrimitiveDoubleObjectInspector) parameters[0];
            }
            outputOI = PrimitiveObjectInspectorFactory.writableDoubleObjectInspector;

            return outputOI;
        }

        @Override
        public AggregationBuffer getNewAggregationBuffer() throws HiveException {
            VarianceBuffer buffer = new VarianceBuffer();
            buffer.init();
            return buffer;
        }

        @Override
        public void reset(AggregationBuffer agg) throws HiveException {
            ((VarianceBuffer) agg).init();
        }

        @Override
        public void iterate(AggregationBuffer agg, Object[] parameters) throws HiveException {
            if (parameters[0] != null) {
                VarianceBuffer buffer = (VarianceBuffer) agg;
                double value = inputOI.get(parameters[0]);
                buffer.count++;
                buffer.sum += value;
                buffer.sumOfSquares += value * value;
            }
        }

        @Override
        public Object terminatePartial(AggregationBuffer agg) throws HiveException {
            // 返回部分聚合结果
            VarianceBuffer buffer = (VarianceBuffer) agg;
            Object[] result = new Object[3];
            result[0] = new DoubleWritable(buffer.count);
            result[1] = new DoubleWritable(buffer.sum);
            result[2] = new DoubleWritable(buffer.sumOfSquares);
            return result;
        }

        @Override
        public void merge(AggregationBuffer agg, Object partial) throws HiveException {
            if (partial != null) {
                VarianceBuffer buffer = (VarianceBuffer) agg;
                Object[] partialResult = (Object[]) partial;
                buffer.count += ((DoubleWritable) partialResult[0]).get();
                buffer.sum += ((DoubleWritable) partialResult[1]).get();
                buffer.sumOfSquares += ((DoubleWritable) partialResult[2]).get();
            }
        }

        @Override
        public Object terminate(AggregationBuffer agg) throws HiveException {
            VarianceBuffer buffer = (VarianceBuffer) agg;
            if (buffer.count == 0) {
                return null;
            }
            double mean = buffer.sum / buffer.count;
            double variance = (buffer.sumOfSquares - buffer.sum * mean) / buffer.count;
            return new DoubleWritable(variance);
        }
    }
}

使用场景:

SELECT VARIANCE(salary) FROM employees;

计算 employees 表中 salary 列的工资方差。

3. UDTF(User Defined Table-Generating Function) - 用户自定义表生成函数

定义

UDTF 是一种用户自定义的表生成函数,它接受一行输入,但可以返回多行甚至多列数据。它的作用类似于 SQL 中的 EXPLODE,将一行数据拆分成多行。

优势
  • 能够从单行数据生成多行或多列数据,适合进行数据拆分和结构化。
  • 非常灵活,能够处理复杂的多行、多列数据生成场景。
  • 适合需要扩展一行数据到多行数据的场景。
劣势
  • 实现复杂度较高:与 UDF 和 UDAF 相比,UDTF 需要处理更多的输出逻辑。
  • 性能较差:由于 UDTF 会输出多行数据,可能会引入较大的开销,特别是当输出数据量大时。
适用场景
  • 适合将一行数据拆分成多行数据的场景,如列表拆分、JSON 解析等。
  • 适合处理复杂的表生成操作,如跨多列的数据展开或分组。
示例

假设有一列存储了逗号分隔的字符串,需要将其拆分成多行,可以编写一个 UDTF。

public class ExplodeUDTF extends GenericUDTF {
    @Override
    public void process(Object[] args) throws HiveException {
        String input = args[0].toString();
        for (String word : input.split(",")) {
            forward(new Object[]{word});
        }
    }
}

使用场景:

SELECT EXPLODE(split_col) FROM table_with_comma_separated_data;

将 table_with_comma_separated_data 表中 split_col 列中的逗号分隔字符串拆分成多行。


UDF、UDAF、UDTF 的比较

特性UDFUDAFUDTF
处理的输入一行数据多行数据一行数据
输出单个结果单个聚合结果多行或多列数据
优点实现简单,适合单行数据处理适合复杂的聚合操作,如求和、平均值等适合数据拆分、扩展多行数据
缺点不能处理多行或表级别的操作实现复杂,需要维护状态实现复杂,性能可能较差
适用场景单列转换,如格式化、数据清洗多行聚合操作,如汇总、统计一行拆分多行,如 JSON 解析,列表拆分
使用示例SELECT UPPER(col)SELECT SUM(col)SELECT EXPLODE(col)

总结

  • UDF:适用于列级的简单数据转换和计算,如格式化、字符串处理等。
  • UDAF:适合需要对多行数据进行聚合的场景,如求和、求平均等。
  • UDTF:适合需要将一行数据拆分成多行的情况,如数组或字符串拆分。

每种函数类型都有其独特的优缺点,选择哪一种取决于具体的数据处理需求和应用场景。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2149151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

骨传导耳机哪个牌子好?盘点口碑最好的5款骨传导耳机!

在快节奏的现代生活中,耳机成为了我们与外界沟通的重要桥梁,无论是在通勤路上、健身锻炼,还是在工作学习中,耳机都扮演着不可或缺的角色。而在众多耳机类型中,骨传导耳机以其独特的声音传导方式和健康舒适的佩戴体验&a…

C语言中的assert断言

Assert断言 断言是程序中处理异常的一种高级形式。可以在任何时候启用和禁用断言验证,因此可以在测试时启用断言,而在部署时禁用断言。同样,程序投入运行后,最终用户在遇到问题时可以重新启用断言。 用法: #…

Qt窗口——QDockWidget

文章目录 浮动窗口浮动窗口使用示例 浮动窗口 QDockWidget浮动窗口可以认为是子窗口,每一个子窗口都可以停靠在四周,像Qt Creator页面,就很多的子窗口: 浮动窗口使用示例 创建: QDockWidget* dockWidget new QDock…

宝马I-Plus手动变速器、K手动变速器、G手动变速器解析

(一) I-Plus手动变速器 1、技术特点 (1)改进齿轮组件结构。I-Plus手动变速器采用第四挡(直接挡)高转速方案,这样可以在保持轴中心距不变的前提下减小啮合力。由此提高驱动力矩后,使得在带有N53B3000发动机的528i车型上首次使用 I 手动变速器。 对啮合面几…

Python精选200Tips:151-155

实战项目 P151--气象数据爬取技术栈:数据爬虫P152--求解数独问题技术栈:代码逻辑+回溯法P153--疾病传播模型的100天模拟技术栈:SIR 模型(易感-感染-恢复模型)P154--复杂函数的最值求解技术栈:粒子群优化算法P155-- 评论情感分析技术栈:snownlp和jieba的应用运行系统:ma…

Opencv+Cuda编译的保姆级别教程

OpencvCuda编译的保姆级别教程 一、环境总览二、环境准备2.1 opencv和opencv扩展2.2 cuda环境下载2.2.1 首先电脑要有英伟达的显卡2.2.2 然后查看显卡驱动版本2.2.3 下载Cuda Toolkit工具包2.2.4 下载Cudnn库 2.3 CMake下载 三、CMake配置步骤3.1 加载路径第一次Configure3.1.1…

前端——表格、列表标签

今天我们来学习一下web开发里面的表格标签、列表标签 常用快捷键&#xff1a; shift alt 下 复制粘贴选中内容 表格标签 table HTML 表格由 <table> 标签来定义。 HTML 表格是一种用于展示结构化数据的标记语言元素。 每个表格均有若干行&#xff08;由 <tr>…

yolov5测试代码

一般源码的测试代码涉及很多文件&#xff0c;因项目需要写一个独立测试的代码。传入的是字典 import time import cv2 import os import numpy as np import torch from modules.detec.models.common import DetectMultiBackend from modules.detec.utils.dataloaders import …

京东商品属性的详细api数据解析:颜色、尺寸与材质

京东&#xff08;JD.com&#xff09;作为一个大型电商平台&#xff0c;其商品信息通过API接口提供给开发者或第三方服务使用&#xff0c;以便进行商品搜索、展示、分析等操作。然而&#xff0c;直接访问京东的详细商品属性&#xff08;如颜色、尺寸、材质等&#xff09;API通常…

数据的表示和存储 第2讲 定点数的编码表示

​ 互联网行业 算法研发工程师 ​ 全文概括&#xff1a; 本讲介绍了定点数的编码表示&#xff0c;主要包括原码、补码和移码。 原码表示方式简单&#xff0c;正数用0表示&#xff0c;负数用1表示&#xff0c;但存在表示不唯一和加减运算不统一的问题。 补码表示方式解决了…

zabbix“专家坐诊”第256期问答

原作者&#xff1a;乐维社区 原文链接&#xff1a;https://forum.lwops.cn/questions 问题一 Q&#xff1a;zabbix 6.4.18版本的&#xff0c;使用zabbix_agentd2监控mysql数据库&#xff0c;只能在界面配置mysql的相关信息吗&#xff1f;这个在zabbix表里面是明文存储的&#x…

集采良药:从“天价神药”到低价良药,伊马替尼的真实世界研究!

在医疗科技日新月异的今天&#xff0c;有一种药物以其卓越的疗效和深远的影响力&#xff0c;成为了众多患者心中的“精准武器”——伊马替尼。这款药物不仅在慢性髓细胞白血病&#xff08;CML&#xff09;的治疗上屡创佳绩&#xff0c;更是胃肠道间质瘤&#xff08;GIST&#x…

微信小程序自定义navigationBar顶部导航栏(背景图片)适配所有机型,使用tdesign-miniprogram t-navbar设置背景图片

设置导航栏样式自定义 一定要设置&#xff0c;不然页面会出现一个原生的导航栏&#xff0c;一个自定义的 // app.json文件 "window": {"navigationStyle": "custom" }设置导航栏样式 我这里使用tdesign-miniprogram t-navbar&#xff0c;t-na…

大模型的热度正在下降,大模型的未来在哪里?

“ 技术是一个需要沉淀和厚积薄发的过程 ” 任何事物都会经过起步&#xff0c;发展&#xff0c;顶峰&#xff0c;平稳&#xff0c;下降&#xff0c;灭亡的过程&#xff0c;大模型技术也不例外。 而从现今的趋势来看&#xff0c;大模型的热度正在不断下降&#xff0c;这到底意…

虫情测报灯的工作原理

型号&#xff1a;TH-CQ1】虫情测报灯是一种专门用于监测农田、林区等环境中昆虫数量和种类的设备&#xff0c;也称为智能虫情测报灯或物联网虫情测报灯。它通过特定的光源和颜色吸引昆虫&#xff0c;并利用高压电网或远红外自动处理技术等手段将昆虫击杀或处理&#xff0c;从而…

《黑龙江水产》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《黑龙江水产》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第一批认定 学术期刊。 问&#xff1a;《黑龙江水产》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;黑龙江省农业农村厅 …

【QT】系统-下

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;QT 目录 &#x1f449;&#x1f3fb;QTheadrun() &#x1f449;&#x1f3fb;QMutex&#x1f449;&#x1f3fb;QWaitCondition&#x1f449;&#x1f3fb;Q…

视频存储EasyCVR视频监控汇聚管理平台设备录像下载报错404是什么原因?

EasyCVR视频监控汇聚管理平台是一款针对大中型项目设计的跨区域网络化视频监控集中管理平台。该平台不仅具备视频资源管理、设备管理、用户管理、运维管理和安全管理等功能&#xff0c;还支持多种主流标准协议&#xff0c;如GB28181、RTSP/Onvif、RTMP、部标JT808、GA/T 1400协…

基于SpringBoot的智能排课系统设计与实现

文未可获取一份本项目的java源码和数据库参考。 &#xff08;一&#xff09;选题来源与背景 高校的每学期伊始&#xff0c;排课是教务处工作中的重中之重。安排合理无资源冲突&#xff08;教师、教室和设备等教学资源&#xff09;的课表是教务工作必须面临的问题。传统的人工…

规模化电动汽车接入配电网调度方法

规模日益增长的电动汽车和可再生能源带来的不确定性给配电网的安全运营带来了严峻挑战。为综合考虑多重不确定性、平衡运营成本与系统可靠性,首先,提出一种基于分布鲁棒联合机会约束的电动汽车-配电网充放电调度模型。该模型将节点电压、支路功率、备用需求等通过联合机会约束建…