hive函数全解析:从内置函数到自定义函数的实战指南
Hive 提供了丰富的函数库,包括内置函数(UDF、UDAF、UDTF)和自定义函数,满足数据清洗、转换、聚合等复杂分析需求。本文详细讲解 Hive 函数的分类、常用内置函数(尤其是窗口函数)的用法,以及自定义函数的开发流程,帮助开发者高效处理数据。
Hive 函数基础与分类
Hive 函数按输入输出关系可分为三类,覆盖不同的数据处理场景:
函数分类
类型 | 全称 | 作用 | 示例 |
---|---|---|---|
UDF | User-Defined Function | 一进一出(单条记录输入,单条结果输出) | concat() 、nvl() |
UDAF | User-Defined Aggregate Function | 多进一出(多条记录输入,单条聚合结果输出) | sum() 、avg() 、collect_set() |
UDTF | User-Defined Table-Generating Function | 一进多出(单条记录输入,多条结果输出) | explode() 、split() |
函数查询与帮助
查看所有内置函数:
1
hive> show functions; -- 列出所有可用函数
查看函数用法:
1
2
3
4-- 基础说明
hive> desc function concat;
-- 详细说明(含示例)
hive> desc function extended concat;模糊查询函数:
1
hive> desc function like '*date*'; -- 查找含“date”的函数
常用内置函数详解
数据清洗与转换函数
空值处理:nvl
为 NULL
值赋默认值,避免计算异常。
1 | nvl(value, default_value) -- 若 value 为 NULL,返回 default_value,否则返回 value |
字符串拼接:concat
与 concat_ws
concat
:拼接多个字符串,任意参数为NULL
则返回NULL
。1
2
3
4concat(str1, str2, ...)
-- 示例:拼接姓名和部门
select concat(ename, '_', deptno) from emp; -- 输出:'张三_10'concat_ws
:指定分隔符拼接字符串,支持数组输入,忽略NULL
。1
2
3
4concat_ws(separator, str1, str2, ...) -- separator 为分隔符
-- 示例:用逗号拼接姓名、部门、薪资
select concat_ws(',', ename, deptno, sal) from emp; -- 输出:'张三,10,5000'
字符串切割与展开:split
与 explode
split
:按正则表达式切割字符串为数组(UDTF 输入)。1
2
3
4split(str, regex) -- 按 regex 切割 str,返回数组
-- 示例:切割逗号分隔的标签
select split('java,python,sql', ',') as tags from dual; -- 输出:["java","python","sql"]explode
:将数组或 Map 拆分为多行(UDTF 输出)。1
2
3
4
5
6
7
8explode(array) -- 将数组元素拆分为多行
-- 示例:展开标签数组
select explode(split('java,python,sql', ',')) as tag from dual;
-- 输出:
java
python
sql
侧视图:lateral view
与 explode
结合,解决 UDTF 不能直接与其他列共存的问题(UDTF 需单独使用)。
1 | lateral view UDTF(expression) 别名 as 列名 |
日期与时间函数
Hive 日期函数支持时间戳、字符串格式转换,满足时序分析需求。
日期格式化:date_format
将日期字符串转换为指定格式(仅支持 yyyy-MM-dd
、yyyy-MM-dd HH:mm:ss
等标准格式)。
1 | date_format(date_str, format) |
时间戳转换:from_unixtime
与 unix_timestamp
from_unixtime
:将 Unix 时间戳(秒级)转为日期字符串。1
2
3
4from_unixtime(timestamp, format)
-- 示例:时间戳转日期
select from_unixtime(1696108800, 'yyyy-MM-dd'); -- 输出:2023-10-01(对应时间戳的日期)unix_timestamp
:将日期字符串转为 Unix 时间戳(支持自定义格式)。1
2
3
4unix_timestamp(date_str, format) -- 若不指定 format,默认解析 'yyyy-MM-dd HH:mm:ss'
-- 示例:自定义格式字符串转时间戳
select unix_timestamp('2023/10/01', 'yyyy/MM/dd'); -- 输出:1696108800
跨格式日期转换:from_unixtime + unix_timestamp
结合两者实现非标准格式日期的转换(如 yyyy/MM/dd
转 yyyyMMdd
)。
1 | -- 示例:将 '2023/10/01' 转为 '20231001' |
聚合函数:collect_set
与 sum
collect_set
:聚合列值为去重数组(UDAF),常用于多值合并。1
2
3
4
5collect_set(col) -- 返回无重复元素的数组
-- 示例:聚合每个部门的员工姓名
select deptno, collect_set(ename) from emp group by deptno;
-- 输出:10 ["张三","李四"]sum
/avg
/count
:基础聚合函数,与group by
配合使用。1
2-- 示例:计算每个部门的平均薪资
select deptno, avg(sal) as avg_sal from emp group by deptno;
窗口函数:over()
高级分析
窗口函数是 Hive 数据分析的核心工具,允许在保留原始数据的同时进行聚合计算,支持定义 “数据窗口”(分析范围)。
窗口函数基础语法
1 | 分析函数(列) OVER ( |
无窗口限制:全局聚合
未指定 PARTITION BY
和 ORDER BY
时,窗口为整个数据集。
1 | -- 示例:计算所有员工的总薪资,保留每行原始数据 |
按列分区:PARTITION BY
按指定列分组,组内独立计算窗口(类似 group by
但保留明细)。
1 | -- 示例:按部门分区,计算每个部门的总薪资 |
定义窗口范围:ROWS BETWEEN
通过 ROWS
或 RANGE
限制窗口内的行数(如 “当前行及前 2 行”)。
范围关键字 | 含义 |
---|---|
CURRENT ROW |
当前行 |
n PRECEDING |
往前 n 行 |
n FOLLOWING |
往后 n 行 |
UNBOUNDED PRECEDING |
从分组第一行开始 |
UNBOUNDED FOLLOWING |
到分组最后一行结束 |
示例:计算累计薪资
1 | -- 按薪资升序,计算从第一行到当前行的累计薪资 |
排序与排名函数:rank
/dense_rank
/row_number
用于组内排序,返回每行的排名序号,差异如下:
函数 | 特点 | 示例(薪资排序) |
---|---|---|
rank() |
相同值排名相同,后续排名跳过 | 1, 2, 2, 4 |
dense_rank() |
相同值排名相同,后续排名连续 | 1, 2, 2, 3 |
row_number() |
相同值排名不同,按顺序递增 | 1, 2, 3, 4 |
示例:部门内薪资排名
1 | select ename, deptno, sal, |
自定义函数开发:UDF 实战
当内置函数无法满足需求时,可开发自定义函数(UDF)。以下以 “小写转大写” UDF 为例,讲解开发流程。
开发环境准备
依赖配置(Maven pom.xml
)
1 | <dependencies> |
UDF 实现类
继承 org.apache.hadoop.hive.ql.exec.UDF
,重写 evaluate
方法(核心逻辑)。
1 | import org.apache.hadoop.hive.ql.exec.UDF; |
打包与部署
打包
用 Maven 打包为 JAR 文件(如 hive-udf-demo.jar
)。
临时函数注册(当前会话有效)
上传 JAR 到 Hive 客户端所在机器;
在 Hive 中添加 JAR 并注册函数:
1 | -- 添加 JAR |
永久函数注册(全局有效)
将 JAR 上传到 HDFS 路径(如
/user/hive/udf/
);注册永久函数:
1
2hive> create function upper_udf as 'com.example.UpperCaseUDF'
using jar 'hdfs:///user/hive/udf/hive-udf-demo.jar';
使用自定义函数
1 | hive> select upper_udf('hello hive'); -- 输出:HELLO HIVE |
函数使用注意事项
- 空值处理:多数函数对
NULL
敏感(如concat
遇NULL
返回NULL
),需用nvl
提前处理。 - 性能优化:
- 避免在
where
中使用复杂函数(如date_format
),可提前预处理; - 窗口函数数据量大时,合理设置
PARTITION BY
减少窗口大小。
- 避免在
- 自定义函数限制:
- UDF 仅支持单条记录处理,复杂聚合需用 UDAF;
- 永久函数需确保 HDFS JAR 路径对所有节点可见。
v1.3.10