大数据Hive中的UDF:自定义数据处理的利器(上)


文章目录

    • 1. 前言
    • 2. UDF与宏及静态表的对比
    • 3. 深入理解UDF
    • 4. 实现自定义UDF

1. 前言

在大数据技术栈中,Apache Hive 扮演着数据仓库的关键角色,它提供了丰富的数据操作功能,并通过类似于 SQLHiveQL 语言简化了对 Hadoop 数据的处理。然而,内置函数库虽强大,却未必能满足所有特定的业务逻辑需求。此时,用户定义函数(User-Defined FunctionsUDF)的重要性便凸显出来。

Hive UDFUser-Defined Function)是Hive中的一种扩展机制,它允许用户通过编写自定义的Java代码来扩展Hive的功能,实现Hive内置函数无法提供的一些特定数据处理逻辑。

2. UDF与宏及静态表的对比

除了UDF可以自定义输入和输出还有例如静态表,宏定义的方式也可以实现类似的操作,举个例子:在数据中筛选出已达到退休年龄的员工。

UDF 示例

import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;public class RetirementStatusUDF extends UDF {public Text evaluate(int age) {return new Text(age >= 60 ? "已达到退休年龄" : "未达到退休年龄");}
}-- 添加UDF的jar包到Hive
ADD JAR /path/to/udf.jar;-- 创建临时函数
CREATE TEMPORARY FUNCTION retirement_status AS 'com.example.RetirementStatusUDF';-- 使用UDF进行查询
SELECT name, age, retirement_status(age) AS status
FROM employee_static;

静态表


CREATE TABLE employee_static (age INT,flag STRING -- 'retired' 或 'active'
);-- 查询已达到退休年龄的员工
SELECT a.*
FROM employee_data a
JOIN employee_static b
ON a.age = b.age AND b.flag = 'retired';

宏定义

drop temporary macro if exists get_retired;create temporary macro get_retired(age bigint) 
if (age is not null,casewhen age >= 60 then '退休'when age <= 60 then '未退休'else nullend,null
);

使用UDF(用户定义函数)的原因与宏和静态表的功能有所不同,它们各自适用于不同的场景和需求。以下是使用UDF的几个关键原因:

特性/方法UDF(用户定义函数)宏(Macro)静态表(Static Table)
定义允许用户通过编写自定义的Java代码来扩展Hive的功能,实现特定的数据处理逻辑。在Hive中,宏是一种用户定义的快捷方式,用于封装一系列HiveQL语句,以便在查询中重复使用。预先定义和填充的数据集,其结构和内容在创建后通常保持不变。
使用场景适用于执行Hive内置函数不支持的特定数据处理逻辑,如复杂的业务规则或算法。主要用于简化和重用HiveQL查询语句,提高代码的可读性和易维护性。适用于存储已知的、不变的数据集,供多次查询使用,无需每次重新计算。
灵活性高,可以根据需求定制数据处理流程。中等,主要用于简化复杂的查询,但不具备动态处理能力。低,结构和内容一旦定义,通常不发生变化。
性能可优化,Hive执行UDF时会进行优化,性能接近内置函数。取决于宏定义的查询的复杂性,可能提高或降低性能。预先计算,查询时性能较高,适合重复查询相同数据集。
重用性高,一旦创建和注册,可以在不同的Hive会话中重复使用。高,宏可以定义一次并在多个查询中重复使用。中等,表结构和数据不变,适用于重复查询相同数据集的场景。
实时性支持实时数据处理,每次调用UDF时根据输入动态执行计算。不直接支持实时数据处理,主要用于查询语句的封装。不支持实时数据处理,通常是预先计算和存储的。
适应性强,可以快速适应新的数据处理需求。中等,需要修改宏定义以适应新的需求。弱,结构和数据固定,不适合频繁变化的数据需求。
示例应用用于实现如复杂数学计算、自定义字符串处理、数据清洗等。用于封装复杂的查询模板,如多步骤的数据转换过程。用于存储配置数据、参考数据或不需要频繁更新的数据。

选择使用UDF、宏还是静态表应基于具体的业务需求、数据特性和性能考虑。每种方法都有其独特的优势和适用场景。

3. 深入理解UDF

Hive UDF可以分为三种主要类型:UDF、UDAF和UDTF。

  1. UDF (User-Defined Function)
    • 标量函数,用于一对一(one-to-one)的映射,即对单个数据项进行操作并返回单个结果。
    • 例如,字符串处理(upper, substr)、数学计算(sqrt)、日期时间转换等。
  2. UDAF (User-Defined Aggregate Function)
    • 聚合函数,用于多对一(many-to-one)的映射,即对多行数据进行聚合操作并返回单个结果。
    • 例如,自定义的求和(sum)、平均值(avg)、最大值(max)、最小值(min)等。
  3. UDTF (User-Defined Table-Generating Function)
    • 表生成函数,用于一对多(one-to-many)的映射,即对单个数据项进行操作并返回多行结果。
    • 例如,explode函数可以将数组或Map类型的列拆分成多行。
类别简称全称描述示例
UDFUser-Defined Function用于实现一对一的映射,即一个输入对应一个输出。将字符串转换为大写。
UDAFUser-Defined Aggregate Function用于实现一对多的映射,即多个输入对应一个输出。计算某个字段的总和或平均值。
UDTFUser-Defined Table-Generating Function用于实现一对多的行生成,即一个输入可以产生多行输出。将数组或映射类型的字段展开成多行数据。

这些UDF类型允许开发者根据特定的数据处理需求,编写和实现自定义的函数逻辑,从而扩展Hive的数据处理能力。通过使用UDF、UDAF和UDTF,用户可以在Hive中实现更加复杂和定制化的数据处理任务。

实现一个UDF通常涉及以下步骤:

  1. 编写UDF类:在Java中创建一个类,实现Hive UDF接口的相应方法。对于标量UDF,这通常是evaluate方法。
  2. 编译与打包:将UDF类编译成Java字节码,并打包成JAR文件。
  3. 上传JAR包:将JAR文件上传到HDFS或其他Hive可以访问的文件系统中。
  4. 注册UDF:在Hive会话中使用ADD JARCREATE TEMPORARY FUNCTION命令注册UDF。
  5. 使用UDF:在Hive查询中调用注册的UDF,就像调用内置函数一样。

4. 实现自定义UDF

在深入探讨Hive UDF的实现之前,让我们首先确保开发环境的准备妥当。对于UDF的编写,推荐使用Maven来配置Java项目,这样可以方便地管理依赖和构建过程。以下是配置Java开发环境的一个示例,包括使用的版本信息和Maven设置:

Apache Maven 3.9.6
Java version: 1.8.0_211,


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>project202401</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><hadoop.version>3.1.1.7.1.7.2000-305</hadoop.version><hive.version>3.1.3000.7.1.7.2000-305</hive.version></properties><dependencies><dependency><groupId>org.apache.hive</groupId><artifactId>hive-exec</artifactId><version>${hive.version}</version><scope>provided</scope></dependency><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-common</artifactId><version>${hadoop.version}</version><scope>provided</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.10.1</version><scope>test</scope></dependency></dependencies><repositories><repository><id>central</id><name>Maven Central</name><url>https://repo1.maven.org/maven2/</url></repository><repository><id>cloudera</id><name>Cloudera Repository</name><url>https://repository.cloudera.com/artifactory/cloudera-repos/</url></repository></repositories></project>

下面是一个Hive UDF(用户定义函数)的示例,该UDF的作用是将传入的字符串转换为大写形式。我将对代码进行注释,并解释其工作流程:


import org.apache.hadoop.io.Text;  // 引入Hadoop的Text类,用于处理字符串
import org.apache.hadoop.hive.ql.exec.UDF;  // 引入Hive的UDF类@SuppressWarnings({"deprecation", "unused"})  // 忽略警告,例如未使用的警告或过时API的警告
public class UpperCaseUDF extends UDF {  // 定义一个名为UpperCaseUDF的类,继承自UDF/*** 该方法重写了UDF类中的evaluate方法,是UDF的核心。* 它接收一个Text类型的数据,然后返回转换为大写的Text类型数据。** @param line Text类型的输入数据* @return 转换为大写的Text类型的数据*/public Text evaluate(final Text line) {// 检查传入的Text是否为非空且内容不为空字符串if (null != line && !line.toString().equals("")) {// 将Text转换为String,并使用String的toUpperCase方法转换为大写String str = line.toString().toUpperCase();// 将大写字符串重新设置回Text对象,并返回line.set(str);return line;} else {// 如果传入的Text为null或空字符串,则返回一个新的空Text对象return new Text();}}
}

在Hive的较新版本中,推荐使用GenericUDF而不是直接继承UDF。以下是使用GenericUDF实现的UpperCaseUDF2的示例代码,以及对代码的详细解释和工作流程分析:


import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.hive.ql.udf.UDFType;@UDFType(deterministic = true, stateful = false) // 标注UDF的特性,确定性且无状态
public class UpperCaseUDF2 extends GenericUDF { // 继承自GenericUDFprivate StringObjectInspector inputOI; // 输入对象检查员,用于检查输入类型private StringObjectInspector outputOI; // 输出对象检查员,用于定义输出类型/*** initialize方法在UDF首次执行时被调用,用于初始化UDF。* @param arguments 传入的参数对象检查员数组* @return 输出对象检查员* @throws UDFArgumentException 如果输入参数不符合预期,抛出异常*/@Overridepublic ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {// 确保传入的参数是字符串类型if (arguments == null || arguments.length == 0) {throw new UDFArgumentException("arguments array is null or empty.");}if (!(arguments[0] instanceof StringObjectInspector)) {// 如果不是字符串类型,抛出Hive异常throw new UDFArgumentException("The input to UpperCaseUDF2 must be a string");}// 将输入参数的对象检查员赋值给局部变量inputOI = (StringObjectInspector) arguments[0];// 定义输出对象检查员为可写的字符串对象检查员outputOI = PrimitiveObjectInspectorFactory.writableStringObjectInspector;// 返回输出对象检查员return outputOI;}/*** evaluate方法定义了UDF的实际逻辑,即如何将输入转换为输出。* @param arguments 包含延迟计算的输入对象的数组* @return 转换后的大写文本* @throws HiveException 如果在执行过程中遇到Hive异常*/@Overridepublic Object evaluate(DeferredObject[] arguments) throws HiveException {// 从延迟对象中获取输入字符串Text line = (Text) arguments[0].get();// 如果输入不为空,则转换为大写if (line != null && !line.toString().isEmpty()) {return new Text(line.toString().toUpperCase());}// 如果输入为空,返回空字符串return new Text();}/*** getDisplayString方法返回UDF的可读字符串表示,用于Hive日志和解释计划。* @param strings 输入参数的字符串表示,通常由Hive自动生成* @return UDF的可读字符串表示*/@Overridepublic String getDisplayString(String[] strings) {// 返回UDF的名称,用于解释计划和日志return "UpperCaseUDF2()";}
}
add jar URL/project202401-1.0-SNAPSHOT.jar;
create temporary function UpperCaseUDF as 'com.xx.hive.udf.UpperCaseUDF';
select UpperCaseUDF('Hive Is Fun') a ;

HIVE IS FUN

通过以上步骤,我们能够创建出高效、可靠的Hive UDF,以满足特定的数据处理需求。UDF的开发不仅需要关注功能的实现,还要重视性能优化和代码的可维护性。正确地使用UDF可以显著提升数据处理的效率,为用户提供强大的数据操作能力。

因为篇幅有限,后面两种自定义UDF,会在下一篇博文展开叙述。

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

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

相关文章

flutter(学习日记篇-1)

windows配置开发环境等 1.下载sdk---------flutter官网 2.配置环境变量 ①在系统中找到环境变量的配置位置&#xff0c;在用户变量模块中选中变量为path的项进行编辑&#xff08;没有path就新建&#xff09;&#xff0c;然后找到刚才下载的flutter的位置&#xff0c;点击目录…

综合案例(前端代码练习):猜数字和表白墙

目录 一、猜数字 html代码&#xff1a; 点击 猜 按钮的js代码&#xff1a; 点击 重开游戏 按钮的js代码&#xff1a; 整体代码&#xff1a; 页面效果&#xff1a; 二、留言板 css代码&#xff1a; html代码&#xff1a; js代码&#xff08;主逻辑在这&#xff09;&am…

前端进阶特训营-TDD制造rollup-0

11月22日 然叔(夏然)带着大家写rollup, 全部采用TDD方式开发。 rollup是什么&#xff1f;就是一个打包器。 rollup适合类库场景&#xff0c;工程上使用webpack. mini-rollup项目分为6部分 1.原型 Treeshaking,AST 2.节点遍历器 Walk 3.构造作用域 Scope 4.模块分析函数 analyz…

无损以太网的ROCE革命,队列的缓存空间优化分析

ROCE无损以太网&#xff0c;队列的缓存空间优化 多级缓存架构优化芯片性能&#xff1a;* 缓存空间细分为芯片级、端口级和队列级&#xff0c;实现精细管理。* 无损队列引入Headroom缓存空间&#xff0c;确保数据完整性。 在芯片层面&#xff1a; 静态缓存为端口提供保证的缓存空…

欧鹏RHCE 第三次作业

unit3.远程连接服务实战 作业题目: 1. 一.配置两台主机 主机1. 主机名: server.example.com ip: 172.25.254.100 建立用户timinglee&#xff0c;其密码为timinglee 主机2 主机名&#xff1a;client.example.com ip: 172.25.254.200 2.安需求完成项目 172.25.254.200 在远程…

2024.4.19作业

1.总结二进制信号量和计数型信号量的区别&#xff0c;以及他们的使用场景。 二进制信号量只有0和1两个状态&#xff0c;如果信号被一个线程接收&#xff0c;那别的线程就无法接收此信号 计数型信号可以累计&#xff0c;可以被多个线程接收 2.使用计数型信号量完成生产者和消费…

【深度学习实战(11)】搭建自己的dataset和dataloader

一、dataset和dataloader要点说明 在我们搭建自己的网络时&#xff0c;往往需要定义自己的dataset和dataloader&#xff0c;将图像和标签数据送入模型。 &#xff08;1&#xff09;在我们定义dataset时&#xff0c;需要继承torch.utils.data.dataset&#xff0c;再重写三个方法…

ModuleNotFoundError: No module named ‘scripts.animatediff_mm‘ 解决方案

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 大家好,我是水滴~~ 本文主要介绍在使用 Stable Diffusion WebUI 安装 AnimateDiff 插件后出现的ModuleNotFoundError: No module named scripts.animatediff_mm异常的解决方案,希望…

第三方应用类---Phpmyadmin 后台 Getshell 操作

免责声明:本节仅做技术交流学习. 目录 什么是Phpmyadmin? getshell前提条件: 详细步骤: 1-搜集到开放phpmyadmin的web,然后访问进去 2-执行SQL命令查看是否开启了读写权限 3-开启了读写权限-->继续 没有开读写权限--->鸡鸡 4-有读写权限之后,执行SQL语句导出文件…

关于edge浏览器点击下载后没有反应的问题解决

不知道什么时候开始&#xff0c;edge浏览器点击下载后没有反应了。 根据网上教程&#xff0c;关闭smartscreen的方式试了没用 后来偶然发现&#xff0c;是因为在扩展里&#xff0c;有一个迅雷下载的扩展&#xff0c;关闭后&#xff0c;就可以正常下载了 具体如下&#xff1a…

Java,Python和Go语言语法差异对比

前段时间一直在找工作&#xff0c;比较颓废&#xff0c;很长时间都没有更新博客了&#xff0c;最近公司的项目需要用到Python语言和Go语言&#xff0c; 所以又重新学习了一下Python语言和Go语言&#xff0c;现在做一些总结&#xff0c;方便以后复习使用&#xff0c;同时也给其他…

扩散卷积模型 笔记

1 Title Diffusion Convolutional Neural Networks&#xff08;James Atwood and Don Towsley&#xff09;【NeurIPS 2016】 2 Conclusion This paper presents diffusion-convolutional neural networks (DCNNs), a new model for graph-structured data. Through the introd…

使用docker搭建GitLab个人开发项目私服

一、安装docker 1.更新系统 dnf update # 最后出现这个标识就说明更新系统成功 Complete!2.添加docker源 dnf config-manager --add-repohttps://download.docker.com/linux/centos/docker-ce.repo # 最后出现这个标识就说明添加成功 Adding repo from: https://download.…

【JavaEE初阶系列】——网络层IP协议(地址管理和路由选择)

目录 &#x1f6a9;网络层 &#x1f388;IP协议 &#x1f469;&#x1f3fb;‍&#x1f4bb;IP协议"拆包组包"功能 &#x1f388;地址管理 &#x1f469;&#x1f3fb;‍&#x1f4bb;IP地址的分类 &#x1f469;&#x1f3fb;‍&#x1f4bb;NAT机制如何工作的…

[阅读笔记20][BTX]Branch-Train-MiX: Mixing Expert LLMs into a Mixture-of-Experts LLM

这篇论文是meta在24年3月发表的&#xff0c;它提出的BTX结构融合了BTM和MoE的优点&#xff0c;既能保证各专家模型训练时的高度并行&#xff0c;又是一个统一的单个模型&#xff0c;可以进一步微调。 这篇论文研究了以高效方法训练LLM使其获得各领域专家的能力&#xff0c;例如…

VBA技术资料MF144:将PDF首页作为对象插入工作表

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套&#xff0c;分为初级、中级、高级三大部分&#xff0c;教程是对VBA的系统讲解&#…

【推理优化】超详细!AIGC面试系列 大模型推理系列(2)

本期问题聚焦于大模型的推理优化技术 本期问题快览 有哪些常见的大模型推理优化技术介绍下通过流水线处理技术来加速大模型推理方案介绍下并行计算技术来加速大模型推理的方案有哪些通过硬件来加速大模型推理的方式&#xff1f;模型量化是如何加速大模型推理的&#xff1f;有哪…

【办公类-21-16】 20240410三级育婴师 344多选题(题目与答案合并word)

作品展示 背景需求&#xff1a; 前文将APP题库里的育婴师题目下载到EXCEL&#xff0c;并进行手动整理【办公类-21-14】 20240406三级育婴师 344道多选题 UIBOT下载整理-CSDN博客文章浏览阅读287次&#xff0c;点赞8次&#xff0c;收藏9次。【办公类-21-14】 20240406三级育婴师…

设计模式-23种基础模式目录

种一棵树最好的时间点是十年前&#xff0c;其次是现在 —— Dambisa Moyo《dead aid》 对软件设计来说&#xff0c;23种基本设计模式就像象棋里面的基本杀法一样。就算你从来没学过基本杀法&#xff0c;从来没听说过二鬼拍门、八角马和双车错这种专业术语&#xff0c;也不代表你…

OpenHarmony鸿蒙南向开发案例:【智能猫眼(基于3518开发板)】

样例简介 本Demo是基于Hi3518开发板&#xff0c;使用开源OpenHarmony开发的RTSP协议流媒体应用。达到将Hi3518开发板中摄像头获取的数据通过RTSP协议传输到手机并显示 。 rtsp实现可参考文档&#xff1a;openharmony_1.0.1实现RTSPServer 运行效果 样例原理 如上图所示&…