hive中udf

本文介绍了如何使用Java和Python实现Hive中的用户自定义函数(UDF),并比较了两种方式的不同之处。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.概述

  尽管hive提供了丰富的函数,但有时依然不能满足用户的需求,此时就需要用户实现UDF。  
    UDF(user define funtion),用户通过自定义对数据的处理过程,以函数的形式在HiveSQL中使用。
    有两种方式在HiveSQL上实现UDF,1、通过java或是通过JVM实现的其他语言实现UDF; 第二种方式 ,通过 TRANSFORM...AS 语法,使用可执行的脚步语言实现 UDF。 接下来,将分别介绍通过 Java 和 Python 实现 Hive 中的 UDF,最后,比较二者在使用过程中的异同。

     假设有一张 Hive 表,描述订单基本信息:
     
CREATE TABLE IF NOT EXISTS order_base(
id                 INT         COMMENT  '自增ID',      
order_sn           STRING      COMMENT  '订单编号',
user_id            INT         COMMENT  '用户ID',
shop_id            INT         COMMENT  '店铺ID',
add_time           INT         COMMENT  '下单时间',
pay_time           INT         COMMENT  '付款时间',
delivery_name      STRING      COMMENT  '收件人姓名',
delivery_address   STRING      COMMENT  '收件人地址',
delivery_phone     STRING      COMMENT  '收件人电话'
)COMMENT '订单基本信息表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' 
STORED AS TEXTFILE

 现在需要查询收件人地址中出现关键字 大学 的记录,找出对应的 (order_sn, delivery_address),通过 UDF 实现。

2.java实现UDF

  通过 Java 实现 UDF 时,Java 中的类必须继承类 the org.apache.hadoop.hive.ql.exec.UDF。 并且,UDF 的实现过程必须写在名称为 evaluate 的函数中。由于 evaluate 并未在 UDF 父类中具体说明,因此,用户实现的UDF中,函数 evaluate的返回类型和参数可以自己指定。当用户实现的 UDF 在 Hive 中执行时,Hive 将会执行函数 evaluate 中的内容。
  
  
package UDF
import org.apache.hadoop.hive.ql.exec.UDF;

public class FindSpecifiedWords extends UDF{
	
	public int evaluate(String targetWords,String rawWords)
	{
		int found = 0;
		if (rawWords.contains(targetWords)) {
			found = 1;
		}
		return found;
	}
}

import org.apache.hadoop.hive.ql.exec.UDF;


public class FindSpecifiedWords extends UDF{

public int evaluate(String targetWords,String rawWords)
{
int found = 0;
if (rawWords.contains(targetWords)) {
found = 1;
}
return found;
}
}
由于 org.apache.hadoop.hive.ql.exec.UDF 并非 Java 自带库函数,因此,这里需要引用包含 Hive API的 jar 包




用 Java 实现的 UDF 完成了,打包为 hive-udf-java.jar,现在,需要在 HiveQL 中调用。

在 HiveQL 中使用 UDF 前,首先需要添加 jar 包至 Hive 中,对自定义函数 UDF.FindSpecifiedWords 进行注册,可以被 Hive 中脚本使用:

hive> ADD JAR /mnt/whlminds/hive-udf-java.jar;

这里,对 UDF.FindSpecifiedWords 起别名,方便调用:

CREATE TEMPORARY FUNCTION findwords AS 'UDF.FindSpecifiedWords'


上述步骤,实现了 UDF,在Hive中注册,并起别名方便调用,接下来,就可以在 HiveQL 中使用了:
SELECT t1.order_sn, t1.delivery_address
FROM order_base t1 
WHERE t1.pay_time >= UNIX_TIMESTAMP('2015-10-04 00:00:00') 
AND t1.pay_time < UNIX_TIMESTAMP('2015-10-05 00:00:00') 
AND findwords('大学', t1.delivery_address) = 1;

为查询方便,可以将 Hive 中注册,起别名,以及调用过程一起写在SQL脚本 find_specified_order.sql 中:
ADD JAR /mnt/whlminds/hive-udf-java.jar;

CREATE TEMPORARY FUNCTION findwords AS 'UDF.FindSpecifiedWords';

SELECT t1.order_sn, t1.delivery_address
FROM order_base t1 
WHERE t1.pay_time >= UNIX_TIMESTAMP('2015-10-04 00:00:00') 
AND t1.pay_time < UNIX_TIMESTAMP('2015-10-05 00:00:00') 
AND findwords('大学', t1.delivery_address) = 1;

hive> hive -f find_specified_order.sql

3.python实现UDF

 Python 实现 Hive 的 UDF,Python 脚本需要以特定的方式读入和输出,除了必须引用 sys 包外,无须引用其他外部包。

这里,查询出现指定关键字记录的 UDF 的 Python 实现过程 FindSpecifiedWords.py 如下:

#!/usr/bin/python

import sys

for line in sys.stdin:
    order_sn, delivery_address = line.strip().split("\t")

    found = "N"
    pos = delivery_address.decode("utf8").find(u'\u5927\u5b66')
    if(pos > -1):
        found = "Y"
    print "\t".join([order_sn, delivery_address, found])

Python 实现的 UDF,需要批量的读入数据,并一对一的批量输出。其中,u'\u5927\u5b66' 是 大学 的 utf8 的编码。

使用 Python 实现的 UDF 完成后,需要通过 ADD FILE 指令添加至 Hive 中进行注册,无需起别名:

hive > ADD FILE /mnt/whlminds/FindSpecifiedWords.py
注册完后,Python 实现的 UDF 就可以通过 TRANSFORM...AS 在 HiveQL 中使用,语法如下:

SELECT TRANSFORM (<columns>)
USING 'python <python_script>'
AS (<columns>)
FROM <table>;

其中, SELECT 中的 columns 是 FROM 中 table 的列名, 而 AS 中的 columns 是经过 USING 中 Python 脚本 python_script 计算返回的列名。

这里,查找包含指定关键字的 HiveQL 脚本如下:

SELECT t2.order_sn, t2.delivery_address
FROM

(SELECT TRANSFORM (t1.order_sn, t1.delivery_address) 
USING 'python FindSpecifiedWords.py' 
AS (order_sn STRING, delivery_address STRING, found STRING)
FROM order_base t1
WHERE t1.pay_time >= UNIX_TIMESTAMP('2015-10-04 00:00:00')
AND t1.pay_time < UNIX_TIMESTAMP('2015-10-05 00:00:00')) t2

WHERE t2.found = 'Y';
为查询方便,可以将 Hive 中注册,以及调用过程一起写在 SQL 脚本 find_specified_order.sql 中:

ADD FILE /mnt/whlminds/FindSpecifiedWords.py;

SELECT t2.order_sn, t2.delivery_address
FROM

(SELECT TRANSFORM (t1.order_sn, t1.delivery_address) 
USING 'python FindSpecifiedWords.py' 
AS (order_sn STRING, delivery_address STRING, found STRING)
FROM order_base t1
WHERE t1.pay_time >= UNIX_TIMESTAMP('2015-10-04 00:00:00')
AND t1.pay_time < UNIX_TIMESTAMP('2015-10-05 00:00:00')) t2

WHERE t2.found = 'Y';
hive> hive -f find_specified_order.sql


比较:


  • Java 实现 UDF,需要引用包含 Hive API 的外部 jar 包,而 Python 无需引起其他外部包;
  • Java 实现 UDF 后,需要打包后才可被 HiveQL 调用,而通过 Python 实现 UDF 后,可以在 HiveQL 中直接被调用;
  • Java 实现 UDF,对读入和输出数据方式没有要求,实现的 UDF 可以输入一条记录的指定列数据,输出结果可以直接在 HiveQL 的 WHERE 中用于判断条件使用;
  • Python 实现的 UDF,对读入和输出数据方式有特殊要求,需要对 HiveQL 中表的指定列数据批量读入,然后一对一地批量输出,因此,通过 Python 实现的 UDF 可以结合子查询使用。









### Hive中自定义UDF函数的创建与使用 #### 创建临时UDF函数 在Hive中可以通过`CREATE TEMPORARY FUNCTION`语句来注册并使用自定义的UDF(User Defined Function)。此命令允许用户将Java类作为自定义函数引入到查询中。例如: ```sql CREATE TEMPORARY FUNCTION myudf AS 'com.master.HiveUDF.MyUDF'; ``` 上述SQL语句表示将名为`myudf`的临时函数映射至指定的Java类路径`com.master.HiveUDF.MyUDF`[^1]。 对于另一个例子,也可以这样声明: ```sql CREATE TEMPORARY FUNCTION getlen AS 'MyNewUDFDemo'; ``` 这里展示了另一种方式,其中`getlen`被绑定到了`MyNewUDFDemo`这个类上[^2]。 #### 使用已创建的UDF函数 一旦成功注册了一个新的UDF之后,在任何SELECT查询里都可以调用它。比如下面的例子演示了如何利用之前定义好的`myudf`处理`t_user`表中的`name`字段的数据: ```sql SELECT myudf(name) FROM t_user; ``` 这条指令会把每一行记录里的`name`列传递给`myudf()`方法执行相应的转换操作后再输出结果集。 另外需要注意的是如果我们的业务场景涉及到更复杂的结构化或者半结构化的数据类型如JSON字符串时,则可能还需要借助专门设计用来解析这类特殊格式输入值的高级版UDFs实例——即GetJsonObject以及GetJsonArray这两个工具类所提供的功能[^5]。 #### 关于适用范围的选择考量因素 当面对一些只需要简单变换即可完成的任务需求时候选用普通的标准内置算子往往已经足够满足日常开发工作所需;然而针对某些特定领域内的独特计算规则则不得不依赖外部扩展机制来自由定制专属解决方案此时便体现出编写个性化插件的重要性所在。而UDF正好提供了这样一个灵活便捷的技术手段让开发者能够快速实现预期目标同时保持良好的可维护性和复用价值不过其局限之处在于难以应对过于繁琐耗时的操作流程因为这可能会显著影响整体性能表现因此建议仅限于那些相对轻量级易于表达清楚逻辑关系的小型算法单元上去应用该特性[^4]。 ```java // 示例 Java 类 MyUDF.java import org.apache.hadoop.hive.ql.exec.UDF; import org.apache.hadoop.io.Text; public class MyUDF extends UDF { public Text evaluate(Text input){ if(input == null){ return null; } String result = "Processed_" + input.toString(); return new Text(result); } } ``` 以上是一个非常基础版本的UDF实现样例代码片段展示怎样继承自org.apache.hadoop.hive.ql.exec包下的抽象基类并通过覆写evaluate()成员函数达成具体业务目的最终形成可供后续环节直接引用的标准组件形式供实际项目工程采纳实施部署运行测试验证优化迭代等一系列完整生命周期管理活动开展下去直至达到理想效果为止[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值