hive系列(2)---自定义函数UDF

本文介绍如何在Hive中通过自定义UDF实现特定业务需求,包括函数开发、打包部署及调用流程,并展示了字符串转小写及电话号码归属地判断两个实例。

一、自定义UDF

在hql中可以满足大部分的需求,但是可能还有部分特定的业务需要自己自定义函数来实现,下面来模拟实现:
1、表的建立:
t_p

0: jdbc:hive2://mini01:10000> desc t_p;
+-----------+------------+----------+--+
| col_name  | data_type  | comment  |
+-----------+------------+----------+--+
| id        | string     |          |
| name      | string     |          |
+-----------+------------+----------+--+

t_flow

+-----------+------------+----------+--+
| col_name  | data_type  | comment  |
+-----------+------------+----------+--+
| phone     | int        |          |
| flow      | int        |          |
+-----------+------------+----------+--+

hql表的建立就省略了,看看数据:

0: jdbc:hive2://mini01:10000> select * from t_p;
+---------+-----------+--+
| t_p.id  | t_p.name  |
+---------+-----------+--+
| 14      | TIANJUN   |
| 1       | ni        |
| 2       | hao       |
| 3       | wo        |
| 4       | shi       |
| 5       | zhong     |
| 6       | guo       |
| 7       | ren       |
| 8       | ha        |
| 9       | wa        |
| 10      | ni        |
| 12      | wo        |
| 13      | ta        |
+---------+-----------+--+
0: jdbc:hive2://mini01:10000> select * from t_flow;
+---------------+--------------+--+
| t_flow.phone  | t_flow.flow  |
+---------------+--------------+--+
| 136214        | 10           |
| 137123        | 14           |
| 137123        | 14           |
| 136123        | 14           |
| 137123        | 14           |
| 138123        | 14           |
| 137123        | 14           |
| 136127        | 14           |
+---------------+--------------+--+

2、自定义函数的实现:
可以通过重载实现函数的多样性,函数必须是public

package hive.lower;

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

import java.util.HashMap;
import java.util.Map;

/**
 * hive自定义函数
 * Created by tianjun on 2017/3/21.
 */
public class ToLowerCase extends UDF {

    public Map<String,String> province = new HashMap<>();


    //hive使用,必须是public
    public String evaluate(String field){

        String result = field.toLowerCase();
        return result;

    }

    public String evaluate(int number){

        province.put("136","beigjing");
        province.put("137","shanghai");
        province.put("138","wuhan");

        String pnb = String.valueOf(number);
        return province.get(pnb.substring(0,3))==null?"unknow":province.get(pnb.substring(0,3));
    }

    public static void main(String[] args) {
        System.out.println(new ToLowerCase().evaluate(137214));
    }
}

二、步骤

1、打成jar包上传到服务器
2、将jar包添加到hive的classpath

hive>add JAR /root/original-mr.demo-1.0-SNAPSHOT.jar;

3、创建临时函数与开发好的java class关联

Hive>create temporary function province as 'hive.lower.ToLowerCase';

t_p的查询:

0: jdbc:hive2://mini01:10000> select id, province(name) lowerName from t_p;
+-----+------------+--+
| id  | lowername  |
+-----+------------+--+
| 14  | tianjun    |
| 1   | ni         |
| 2   | hao        |
| 3   | wo         |
| 4   | shi        |
| 5   | zhong      |
| 6   | guo        |
| 7   | ren        |
| 8   | ha         |
| 9   | wa         |
| 10  | ni         |
| 12  | wo         |
| 13  | ta         |
+-----+------------+--+

t_flow的查询

0: jdbc:hive2://mini01:10000> select phone,province(phone) province ,flow from t_flow;
+---------+-----------+-------+--+
|  phone  | province  | flow  |
+---------+-----------+-------+--+
| 136214  | beigjing  | 10    |
| 137123  | shanghai  | 14    |
| 137123  | shanghai  | 14    |
| 136123  | beigjing  | 14    |
| 137123  | shanghai  | 14    |
| 138123  | wuhan     | 14    |
| 137123  | shanghai  | 14    |
| 136127  | beigjing  | 14    |
+---------+-----------+-------+--+
### 问题分析 Hive 在注册 UDF(用户自定义函数)时,若出现 `java.net.URISyntaxException: Illegal character in scheme name at index 3: hdf s:///hive/udf_jars/hive-udf-behavior-1.0.0.jar` 错误,表明 JAR 文件路径格式存在异常。Hive 要求使用标准的 URI 格式加载外部 JAR 文件,例如 `hdfs://` 或 `file://`,而错误提示中的路径 `hdf s://` 显然是非法的 URI,因为 `hdf` 不是有效的 URI scheme,且 `s:` 出现在 scheme 名称中,导致解析失败[^1]。 此外,Hive 中若尝试调用未正确注册的函数,如 `url_trans(url)` 或 `get_city_by_ip(client_ip)`,则会抛出 `SemanticException`,提示函数未定义或无效,这通常与 UDF 注册失败或未正确加载 JAR 文件有关[^1]。 ### 问题原因 1. **JAR 路径格式错误**:`hdf s:///hive/udf_jars/hive-udf-behavior-1.0.0.jar` 并不是一个合法的 URI。Hive 要求使用标准的 URI 格式,如 `hdfs://` 或 `file://`,并且路径中不应含空格或其他非法字符。 2. **Hive UDF 注册依赖 ADD JAR 命令**:在 Hive 中注册 UDF 之前,必须使用 `ADD JAR` 命令加载 JAR 文件,否则 Hive 无法找到类路径,导致函数注册失败。 3. **函数类名未正确指定**:在 `CREATE FUNCTION` 语句中,函数对应的 Java 类必须使用完整限定名(名),否则 Hive 无法识别并加载该类。 ### 解决方案 #### 1. 使用合法的 URI 加载 JAR 文件 确保 JAR 文件路径为标准 URI 格式,例如: ```sql ADD JAR hdfs:///hive/udf_jars/hive-udf-behavior-1.0.0.jar; ``` 或使用本地路径: ```sql ADD JAR file:///home/user/hive-udf-behavior-1.0.0.jar; ``` 避免路径中出现非法字符或格式错误,例如 `hdf s://` 或 `/hive/udf_jars/`,这些格式不被 Hive 支持[^1]。 #### 2. 正确注册 UDF 函数 在加载 JAR 文件后,使用 `CREATE FUNCTION` 命令注册函数,并确保类名含完整的路径: ```sql CREATE FUNCTION get_city_by_ip AS 'com.hive.udf.IpToLocUdf'; ``` 其中 `com.hive.udf.IpToLocUdf` 是 UDF 的完整类名。如果类名拼写错误或未名,则 Hive 无法加载该函数,并抛出 `SemanticException` 异常[^1]。 #### 3. 配置 Hive 辅助 JAR 路径 如果 UDF 需要在 Hive 启动时自动加载,可以将 JAR 文件路径添加到 `hive-site.xml` 中的 `hive.aux.jars.path` 配置项: ```xml <property> <name>hive.aux.jars.path</name> <value>file:///home/user/hive-udf-behavior-1.0.0.jar</value> </property> ``` 确保路径格式为 `file://` 或 `hdfs://`,并且文件路径在 Hive 启动时可访问。若路径格式错误或文件不存在,可能导致 Hive 启动失败或 UDF 无法加载。 #### 4. 检查 Hive 会话中的函数调用 在执行查询语句时,确保函数名拼写正确且已在 Hive 会话中注册。例如: ```sql SELECT get_city_by_ip(client_ip) FROM comm.ods_behavior_log LIMIT 10; ``` 若函数未注册或类路径未加载,则会提示 `Invalid function` 错误。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值