hive 虽然自带了很多函数,但是毕竟有限,无法满足所有业务场景,用户可以自定义函数来实现特定功能

 

UDF

user define function,用户自定义函数

可以分为 3 类

UDF:一进一出

UDAF:聚集函数,多进一出,user define aggregation function

UDTF:炸裂函数,一进多出

 

UDF 可以用多种语言实现,如 java、python、hive

 

准备工作

建表

create external table person(
name string,
idcard string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED as TEXTFILE;

外建表,还记得吗?

外建表不能 truncate 清空,如果是 drop 删表,只删除元数据,hdfs 中的数据还在

 

写入如下数据

neil    411326199402110030
pony    41132519950911004x
jcak    12312423454556561
tony    412345671234908

 

Hive Function

即用 hql 来实现 function,这是最简单的,写完 function 直接运行 sql 就行了

复制代码
select idcard,
case when length(idcard) = 18 then
             case when substring(idcard,-2,1) % 2 = 1 then '' 
             when substring(idcard,-2,1) % 2 = 0 then '' 
             else 'unknown' end 
     when length(idcard) = 15 then 
            case when substring(idcard,-1,1) % 2 = 1 then ''
            when substring(idcard,-1,1) % 2 = 0 then ''
            else 'unknown' end
     else '不合法' end 
from person;
复制代码

 

Python UDF

python 也毕竟简单,类似于 mapreduce

复制代码
# -*- coding: utf-8 -*-
import sys

for line in sys.stdin:
    detail = line.strip().split("\t")
    if len(detail) != 2:
        continue
    else:
        name = detail[0]
        idcard = detail[1]
        if len(idcard) == 15:
            if int(idcard[-1]) % 2 == 0:
                print("\t".join([name,idcard,""]))
            else:
                print("\t".join([name,idcard,""]))
        elif len(idcard) == 18:
            if int(idcard[-2]) % 2 == 0:
                print("\t".join([name,idcard,""]))
            else:
                print("\t".join([name,idcard,""]))
        else:
            print("\t".join([name,idcard,"身份信息不合法!"]))
复制代码

输入就是 hive 表的每一行

 

本地测试 UDF

直接在 hive 上测试比较麻烦,我们可以在本地测试下 UDF 写的是否正确,直接命令行即可

cat person.txt|python person.py

 

hive 中使用 UDF

在 hive 中使用 python 编写的 UDF 需要借助 transform 函数,语法如下

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

顾名思义,就是用 python 脚本来转换 某列 生成新的列作为输出

 

第一步:加载 py 文件

在 hive 中执行如下代码

add file /xxx/udf1.py

xxx 为本地路径;

注意在每次启动 hive 后都要重新加载

 

第二步:使用 UDF 查询

select transform(name,idcard) USING 'python udf1.py'  AS (name,idcard,gender) from person;
neil    411326199402110030    男
pony    41132519950911004x    女
jcak    12312423454556561    身份信息不合法!
tony    412345671234908    女

 

vs1

select transform(name,idcard) USING 'python udf1.py'  AS (name,idcard) from person;
neil    411326199402110030
pony    41132519950911004x
jcak    12312423454556561
tony    412345671234908

 

vs2

select transform(name) USING 'python udf1.py'  AS (name,idcard,gender) from person;

可执行,但是无输出

 

转换的列和输出的列在一定程度上保持一致

 

python UDF 是效率比较低的,因为python 直接向系统请求资源,而不是通过 yarn 的 rm 申请,对资源的利用率较低

 

Java UDF 

见官网

 

 

 

参考资料:

https://cwiki.apache.org/confluence/display/hive/hiveplugins  官网  java 用法

https://blog.csdn.net/qq_26937525/article/details/54136317

https://blog.csdn.net/liu82327114/article/details/80670415  讲述了 python udf 的缺点