• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

7、hive shell客户端和属性配置、内置运算符、函数内置运算符和自定义UDF运算符

武飞扬头像
一瓢一瓢的饮 alanchan
帮助2

Apache Hive 系列文章

1、apache-hive-3.1.2简介及部署(三种部署方式-内嵌模式、本地模式和远程模式)及验证详解
2、hive相关概念详解–架构、读写文件机制、数据存储
3、hive的使用示例详解-建表、数据类型详解、内部外部表、分区表、分桶表
4、hive的使用示例详解-事务表、视图、物化视图、DDL(数据库、表以及分区)管理详细操作
5、hive的load、insert、事务表使用详解及示例
6、hive的select(GROUP BY、ORDER BY、CLUSTER BY、SORT BY、LIMIT、union、CTE)、join使用详解及示例
7、hive shell客户端与属性配置、内置运算符、函数(内置运算符与自定义UDF运算符)
8、hive的关系运算、逻辑预算、数学运算、数值运算、日期函数、条件函数和字符串函数的语法与使用示例详解
9、hive的explode、Lateral View侧视图、聚合函数、窗口函数、抽样函数使用详解
10、hive综合示例:数据多分隔符(正则RegexSerDe)、url解析、行列转换常用函数(case when、union、concat和explode)详细使用示例
11、hive综合应用示例:json解析、窗口函数应用(连续登录、级联累加、topN)、拉链表应用
12、Hive优化-文件存储格式和压缩格式优化与job执行优化(执行计划、MR属性、join、优化器、谓词下推和数据倾斜优化)详细介绍及示例
13、java api访问hive操作示例



本文介绍hive shell客户端的属性配置、内置运算符和函数的内容及使用示例。
本文依赖hive环境可用。
本文分为三个部分,即shell客户端属性配置、内置的运算符使用和函数使用。

一、客户端与属性配置

1、CLIs and Commands客户端和命令

学新通

1)、Beeline CLI

$HIVE_HOME/bin/beeline被称之为第二代客户端或者新客户端,是一个JDBC客户端,是官方强烈推荐使用的Hive命令行工具,和第一代客户端相比,性能加强安全性提高。
Beeline在嵌入式模式和远程模式下均可工作。

[alanchan@server4 bin]$ pwd
/usr/local/bigdata/apache-hive-3.1.2-bin/bin
[alanchan@server4 bin]$ beeline
Beeline version 3.1.2 by Apache Hive
beeline> ! connect jdbc:hive2://server4:10000
Connecting to jdbc:hive2://server4:10000
Enter username for jdbc:hive2://server4:10000: alanchan
Enter password for jdbc:hive2://server4:10000: ********
Connected to: Apache Hive (version 3.1.2)
Driver: Hive JDBC (version 3.1.2)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://server4:10000>

2、Configuration Properties属性配置

Hive配置属性是在HiveConf.Java类中管理的,可以参考文件以获取当前使用版中可用的配置属性列表;
从Hive 0.14.0开始,会从HiveConf.java类中直接生成配置模板文件hive-default.xml.template;
详细的配置参数大全可以参考Hive官网配置参数
https://cwiki.apache.org/confluence/display/Hive/Configuration Properties

1)、方式一:hive-site.xml

在$HIVE_HOME/conf路径下,可以添加一个hive-site.xml文件,把需要定义修改的配置属性添加进去,这个配置文件会影响到基于这个Hive安装包的任何一种服务启动、客户端使用方式。比如使用MySQL作为元数据的存储介质,把连接MySQL的相关属性配置在hive-site.xml文件中,这样不管是本地模式还是远程模式启动,不管客户端本地连接还是远程连接,都将访问同一个元数据存储介质。

<configuration>
    <!-- 存储元数据mysql相关配置 -->
    <property>
        <name>javax.jdo.option.ConnectionURL</name>
        <value> jdbc:mysql://node1:3306/hive?createDatabaseIfNotExist=true&amp;useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8</value>
    </property>

    <property>
        <name>javax.jdo.option.ConnectionDriverName</name>
        <value>com.mysql.jdbc.Driver</value>
    </property>
</configuration>

2)、方式二:–hiveconf命令行参数

hiveconf是一个命令行的参数,用于在使用Hive CLI或者Beeline CLI的时候指定配置参数。
这种方式的配置在整个的会话session中有效,会话结束,失效。
比如在启动hive服务的时候,为了更好的查看启动详情,可以通过hiveconf参数修改日志级别:

hive --hiveconf hive.root.logger=DEBUG,console

3)、方式三:set命令

在Hive CLI或Beeline中使用set命令为set命令之后的所有SQL语句设置配置参数,这个也是会话级别的。
这种方式也是用户日常开发中使用最多的一种配置参数方式。
因为Hive倡导一种:谁需要、谁配置、谁使用的一种思想,避免你的属性修改影响其他用户的修改

#启用hive动态分区,需要在hive会话中设置两个参数:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;

4)、方式四:服务特定配置文件

hivemetastore-site.xml、hiveserver2-site.xml
Hive Metastore会加载可用的hive-site.xml以及hivemetastore-site.xml配置文件。
HiveServer2会加载可用的hive-site.xml以及hiveserver2-site.xml。
如果HiveServer2以嵌入式模式使用元存储,则还将加载hivemetastore-site.xml。

5)、配置方式选择

  • 配置方式优先级

set设置 > hiveconf参数 > hive-site.xml配置文件
set参数声明会覆盖命令行参数hiveconf,命令行参数会覆盖配置文件hive-site.xml设定
日常开发使用中,如果不是核心的需要全局修改的参数属性,建议使用set命令进行设置

  • Hive也会读入Hadoop的配置,因为Hive是作为Hadoop的客户端启动的,Hive的配置会覆盖Hadoop的配置

二、Hive内置运算符

Hive支持的运算符可以分为三大类:关系运算、算术运算、逻辑运算。
官方参考文档:https://cwiki.apache.org/confluence/display/Hive/LanguageManual UDF
也可以使用下述方式查看运算符的使用方式

--显示所有的函数和运算符
show functions;
--查看运算符或者函数的使用说明
describe function count;
--使用extended 可以查看更加详细的使用说明
describe function extended count;

1、关系运算符及示例

关系运算符是二元运算符,执行的是两个操作数的比较运算。
每个关系运算符都返回boolean类型结果(TRUE或FALSE)。

  • 环境准备
--1、创建表dual
create table dual(id string);
--2、加载一个文件dual.txt到dual表中
--dual.txt只有一行内容:内容为一个空格
load data local inpath '/root/hivedata/dual.txt' into table dual;
--3、在select查询语句中使用dual表完成运算符、函数功能测试
select 1 1 from dual;

select 1 1;
  • 示例
----------------Hive中关系运算符--------------------------
--is null空值判断
select 1 from dual where 'itcast' is null;

--is not null 非空值判断
select 1 from dual where 'itcast' is not null;

--like比较: _表示任意单个字符 %表示任意数量字符
--否定比较: NOT A like B
select 1 from dual where 'itcast' like 'it_';
select 1 from dual where 'itcast' like 'it%';
select 1 from dual where  'itcast' not like 'hadoo_';
select 1 from dual where  not 'itcast' like 'hadoo_';

--rlike:确定字符串是否匹配正则表达式,是REGEXP_LIKE()的同义词。
select 1 from dual where 'itcast' rlike '^i.*t$';
select 1 from dual where '123456' rlike '^\\d $';  --判断是否全为数字
select 1 from dual where '123456aa' rlike '^\\d $';

--regexp:功能与rlike相同 用于判断字符串是否匹配正则表达式
select 1 from dual where 'itcast' regexp '^i.*t$';
学新通

2、算术运算符及示例

-------------------Hive中算术运算符---------------------------------
--取整操作: div  给出将A除以B所得的整数部分。例如17 div 3得出5。
select 17 div 3;

--取余操作: %  也叫做取模mod  A除以B所得的余数部分
select 17 % 3;

--位与操作: &  A和B按位进行与操作的结果。 与表示两个都为1则结果为1
select 4 & 8 from dual;  --4转换二进制:0100 8转换二进制:1000
select 6 & 4 from dual;  --4转换二进制:0100 6转换二进制:0110

--位或操作: |  A和B按位进行或操作的结果  或表示有一个为1则结果为1
select 4 | 8 from dual;
select 6 | 4 from dual;

--位异或操作: ^ A和B按位进行异或操作的结果 异或表示两者的值不同,则结果为1
select 4 ^ 8 from dual;
select 6 ^ 4 from dual;
学新通

3、逻辑运算符及示例

--3、Hive逻辑运算符
--与操作: A AND B   如果A和B均为TRUE,则为TRUE,否则为FALSE。如果A或B为NULL,则为NULL。
select 1 from dual where 3>1 and 2>1;
--或操作: A OR B   如果A或B或两者均为TRUE,则为TRUE,否则为FALSE。
select 1 from dual where 3>1 or 2!=2;
--非操作: NOT A 、!A   如果A为FALSE,则为TRUE;如果A为NULL,则为NULL。否则为FALSE。
select 1 from dual where not 2>1;
select 1 from dual where !2=1;
--在:A IN (val1, val2, ...)  如果A等于任何值,则为TRUE。
select 1 from dual where 11  in(11,22,33);
--不在:A NOT IN (val1, val2, ...) 如果A不等于任何值,则为TRUE
select 1 from dual where 11 not in(22,33,44);
--逻辑是否存在: [NOT] EXISTS (subquery)
--将主查询的数据,放到子查询中做条件验证,根据验证结果(TRUE 或 FALSE)来决定主查询的数据结果是否得以保留。
select A.* from A
where exists (select B.id from B where A.id = B.id);

--其他运算符
select 'it' || 'cast';
select concat()

select `array`(11,22,33)
from dual;
学新通

三、Hive Functions函数

1、Hive 函数概述及分类标准

通过show functions命令在hive客户端查看当下可用的所有函数;
通过describe function extended funcname命令在hive客户端查看函数的使用方式。

2、分类标准

1)、Hive函数分类

  • Hive的函数分为两大类:内置函数(Built-in Functions)、用户定义函数UDF(User-Defined Functions)
  • 内置函数可分为:数值类型函数、日期类型函数、字符串类型函数、集合函数、条件函数等;
  • 用户定义函数根据输入输出的行数可分为3类:UDF、UDAF、UDTF。
    学新通

2)、根据函数输入输出的行数

  • UDF(User-Defined-Function)普通函数,一进一出
  • UDAF(User-Defined Aggregation Function)聚合函数,多进一出
  • UDTF(User-Defined Table-Generating Functions)表生成函数,一进多出
    学新通

2、Hive 内置函数

内置函数(build-in)指的是Hive已实现好,直接可以使用的函数,也叫做内建函数。
官方文档地址:https://cwiki.apache.org/confluence/display/Hive/LanguageManual UDF
内置函数根据应用归类整体可以分为8大种类型。

1)、String Functions 字符串函数示例

------------String Functions 字符串函数------------
select concat("angela","baby");
--带分隔符字符串连接函数:concat_ws(separator, [string | array(string)] )
select concat_ws('.', 'www', array('win', 'com'));
--字符串截取函数:substr(str, pos[, len]) 或者  substring(str, pos[, len])
select substr("angelababy",-4); --pos是从1开始的索引,如果为负数则倒着数
select substr("angelababy",7,4);
0: jdbc:hive2://server4:10000> select substr("angelababy",-4); 
 ------- 
|  _c0  |
 ------- 
| baby  |
 ------- 
0: jdbc:hive2://server4:10000> select substr("angelababy",7,4);
 ------- 
|  _c0  |
 ------- 
| baby  |
 ------- 

--正则表达式替换函数:regexp_replace(str, regexp, rep)
select regexp_replace('100-200', '(\\d )', 'num');
--正则表达式解析函数:regexp_extract(str, regexp[, idx]) 提取正则匹配到的指定组内容
select regexp_extract('100-200', '(\\d )-(\\d )', 2);
--URL解析函数:parse_url 注意要想一次解析出多个 可以使用parse_url_tuple这个UDTF函数
select parse_url('http://www.win.com/path/p1.php?query=1', 'HOST');
--分割字符串函数: split(str, regex)
select split('apache hive', '\\s ');
--json解析函数:get_json_object(json_txt, path)
--$表示json对象
select get_json_object('[{"website":"www.win.com","name":"allenwoon"}, {"website":"cloud.win.com","name":"carbondata 中文文档"}]', '$.[1].website');
0: jdbc:hive2://server4:10000> select get_json_object('[{"website":"www.win.com","name":"allenwoon"}, {"website":"cloud.win.com","name":"carbondata 中文文档"}]', '$.[1].website');
 ---------------- 
|      _c0       |
 ---------------- 
| cloud.win.com  |
 ---------------- 

--字符串长度函数:length(str | binary)
select length("angelababy");
--字符串反转函数:reverse
select reverse("angelababy");
--字符串连接函数:concat(str1, str2, ... strN)
--字符串转大写函数:upper,ucase
select upper("angelababy");
select ucase("angelababy");
--字符串转小写函数:lower,lcase
select lower("ANGELABABY");
select lcase("ANGELABABY");
--去空格函数:trim 去除左右两边的空格
select trim(" angelababy ");
--左边去空格函数:ltrim
select ltrim(" angelababy ");
--右边去空格函数:rtrim
select rtrim(" angelababy ");
--空格字符串函数:space(n) 返回指定个数空格
select space(4);
--重复字符串函数:repeat(str, n) 重复str字符串n次
select repeat("angela",2);
--首字符ascii函数:ascii
select ascii("angela");  --a对应ASCII 97
--左补足函数:lpad
select lpad('hi', 5, '??');  --???hi
select lpad('hi', 1, '??');  --h
--右补足函数:rpad
select rpad('hi', 5, '??');
--集合查找函数: find_in_set(str,str_array)
select find_in_set('a','abc,b,ab,c,def');
学新通

2)、Date Functions 日期函数

--获取当前日期: current_date
select current_date();
--获取当前时间戳: current_timestamp
--同一查询中对current_timestamp的所有调用均返回相同的值。
select current_timestamp();
--获取当前UNIX时间戳函数: unix_timestamp
select unix_timestamp();
--日期转UNIX时间戳函数: unix_timestamp
select unix_timestamp("2022-10-21 17:47:21");
--指定格式日期转UNIX时间戳函数: unix_timestamp
select unix_timestamp('20221021 17:47:21','yyyyMMdd HH:mm:ss');
--UNIX时间戳转日期函数: from_unixtime
select from_unixtime(1666374441);
select from_unixtime(0, 'yyyy-MM-dd HH:mm:ss');
0: jdbc:hive2://server4:10000> select from_unixtime(0, 'yyyy-MM-dd HH:mm:ss');
 ---------------------- 
|         _c0          |
 ---------------------- 
| 1970-01-01 00:00:00  |
 ---------------------- 
--日期比较函数: datediff  日期格式要求'yyyy-MM-dd HH:mm:ss' or 'yyyy-MM-dd'
select datediff('2022-10-21','2023-10-21');
0: jdbc:hive2://server4:10000> select datediff('2022-10-21','2023-10-21');
 ------- 
|  _c0  |
 ------- 
| -365  |
 ------- 
--日期增加函数: date_add
select date_add('2022-9-21',10);
0: jdbc:hive2://server4:10000> select date_add('2022-9-21',10);
 ------------- 
|     _c0     |
 ------------- 
| 2022-10-01  |
 ------------- 

--日期减少函数: date_sub
select date_sub('2022-10-01',10);


--抽取日期函数: to_date
select to_date('2022-10-21 17:47:21');
--日期转年函数: year
select year('2022-10-21 17:47:21');
--日期转月函数: month
select month('2022-10-21 17:47:21');
--日期转天函数: day
select day('2022-10-21 17:47:21');
--日期转小时函数: hour
select hour('2022-10-21 17:47:21');
--日期转分钟函数: minute
select minute('2022-10-21 17:47:21');
--日期转秒函数: second
select second('2022-10-21 17:47:21');
--日期转周函数: weekofyear 返回指定日期所示年份第几周
select weekofyear('2022-10-21 17:47:21');
学新通

3)、Mathematical Functions 数学函数

--取整函数: round  返回double类型的整数值部分 (遵循四舍五入)
select round(3.1415926);
--指定精度取整函数: round(double a, int d) 返回指定精度d的double类型
select round(3.1415926,4);
--向下取整函数: floor
select floor(3.1415926);
select floor(-3.1415926);
--向上取整函数: ceil
select ceil(3.1415926);
select ceil(-3.1415926);
--取随机数函数: rand 每次执行都不一样 返回一个0到1范围内的随机数
select rand();
--指定种子取随机数函数: rand(int seed) 得到一个稳定的随机数序列
select rand(3);

0: jdbc:hive2://server4:10000> select round(3.1415926);
 ------ 
| _c0  |
 ------ 
| 3    |
 ------ 
0: jdbc:hive2://server4:10000> select round(3.1415926,4);
 --------- 
|   _c0   |
 --------- 
| 3.1416  |
 --------- 
0: jdbc:hive2://server4:10000> select floor(3.1415926);
 ------ 
| _c0  |
 ------ 
| 3    |
 ------ 
0: jdbc:hive2://server4:10000> select floor(-3.1415926);
 ------ 
| _c0  |
 ------ 
| -4   |
 ------ 
0: jdbc:hive2://server4:10000> select ceil(3.1415926);
 ------ 
| _c0  |
 ------ 
| 4    |
 ------ 
0: jdbc:hive2://server4:10000> select ceil(-3.1415926);
 ------ 
| _c0  |
 ------ 
| -3   |
 ------ 
0: jdbc:hive2://server4:10000> select rand();
 ---------------------- 
|         _c0          |
 ---------------------- 
| 0.45830703128392947  |
 ---------------------- 
0: jdbc:hive2://server4:10000> select rand(3);
 -------------------- 
|        _c0         |
 -------------------- 
| 0.731057369148862  |
 -------------------- 
学新通

4)、二进制函数

bin(BIGINT a)
select bin(18);
--进制转换函数: conv(BIGINT num, int from_base, int to_base)
select conv(17,10,16);
--绝对值函数: abs
select abs(-3.9);

0: jdbc:hive2://server4:10000> select bin(18);
 -------- 
|  _c0   |
 -------- 
| 10010  |
 -------- 
0: jdbc:hive2://server4:10000> select conv(17,10,16);
 ------ 
| _c0  |
 ------ 
| 11   |
 ------ 
0: jdbc:hive2://server4:10000> select abs(-3.9);
 ------ 
| _c0  |
 ------ 
| 3.9  |
 ------ 
学新通

5)、Collection Functions 集合函数

--集合元素size函数: 
size(Map<K.V>) 
size(Array<T>)
select size(`array`(11,22,33));
select size(`map`("id",10086,"name","zhangsan","age",18));

--取map集合keys函数: 
map_keys(Map<K.V>)
select map_keys(`map`("id",10086,"name","zhangsan","age",18));
0: jdbc:hive2://server4:10000> select map_keys(`map`("id",10086,"name","zhangsan","age",18));
 ---------------------- 
|         _c0          |
 ---------------------- 
| ["id","name","age"]  |
 ---------------------- 

--取map集合values函数: 
map_values(Map<K.V>)
select map_values(`map`("id",10086,"name","zhangsan","age",18));

--判断数组是否包含指定元素: 
array_contains(Array<T>, value)
select array_contains(`array`(11,22,33),11);
select array_contains(`array`(11,22,33),66);

--数组排序函数:sort_array(Array<T>)
select sort_array(`array`(12,2,32));
学新通

6)、Conditional Functions 条件函数

select * from student limit 3;

describe function extended isnull;

--if条件判断: if(boolean testCondition, T valueTrue, T valueFalseOrNull)
select if(1=2,100,200);
select *,if(sex ='男','M','W') from student limit 3;
0: jdbc:hive2://server4:10000> select if(sex ='男','M','W') from student limit 3;
 ------ 
| _c0  |
 ------ 
| M    |
| W    |
| W    |
 ------ 
3 rows selected (0.107 seconds)
0: jdbc:hive2://server4:10000> select *,if(sex ='男','M','W') from student limit 3;
 -------------- --------------- -------------- -------------- --------------- ------ 
| student.num  | student.name  | student.sex  | student.age  | student.dept  | _c1  |
 -------------- --------------- -------------- -------------- --------------- ------ 
| 95001        | 李勇            | 男            | 20           | CS            | M    |
| 95002        | 刘晨            | 女            | 19           | IS            | W    |
| 95003        | 王敏            | 女            | 22           | MA            | W    |
 -------------- --------------- -------------- -------------- --------------- ------ 


--空判断函数: isnull( a )
select isnull("allen");
select isnull(null);

--非空判断函数: isnotnull ( a )
select isnotnull("allen");
select isnotnull(null);

--空值转换函数: nvl(T value, T default_value)
select nvl("alan","win");
select nvl(null,"win");

--非空查找函数: COALESCE(T v1, T v2, ...)
--返回参数中的第一个非空值;如果所有值都为NULL,那么返回NULL
select COALESCE(null,11,22,33);
select COALESCE(null,null,null,33);
select COALESCE(null,null,null);
0: jdbc:hive2://server4:10000> select COALESCE(null,11,22,33);
 ------ 
| _c0  |
 ------ 
| 11   |
 ------ 

--条件转换函数: CASE a WHEN b THEN c [WHEN d THEN e]* [ELSE f] END
select case 100 when 50 then 'tom' when 100 then 'mary' else 'tim' end;
select case sex when '男' then 'male' else 'female' end from student limit 3;
select *,
    case sex 
        when '男' then 'male' 
            else 'female' end 
from student limit 3;
0: jdbc:hive2://server4:10000> select case sex when '男' then 'male' else 'female' end from student limit 3;
 --------- 
|   _c0   |
 --------- 
| male    |
| female  |
| female  |
 --------- 
3 rows selected (0.095 seconds)
0: jdbc:hive2://server4:10000> select *,case sex when '男' then 'male' else 'female' end from student limit 3;
 -------------- --------------- -------------- -------------- --------------- --------- 
| student.num  | student.name  | student.sex  | student.age  | student.dept  |   _c1   |
 -------------- --------------- -------------- -------------- --------------- --------- 
| 95001        | 李勇            | 男            | 20           | CS            | male    |
| 95002        | 刘晨            | 女            | 19           | IS            | female  |
| 95003        | 王敏            | 女            | 22           | MA            | female  |
 -------------- --------------- -------------- -------------- --------------- --------- 

--nullif( a, b ):
-- 如果a = b,则返回NULL,否则返回一个
select nullif(11,11);
select nullif(11,12);

--assert_true(condition)
--如果'condition'不为真,则引发异常,否则返回null
SELECT assert_true(11 >= 0);
SELECT assert_true(-1 >= 0);
学新通

7)、Type Conversion Functions 类型转换函数

--任意数据类型之间转换:cast
select cast(12.14 as bigint);
select cast(12.14 as string);
select cast("hello" as int);
0: jdbc:hive2://server4:10000> select cast("hello" as int);
 ------- 
|  _c0  |
 ------- 
| NULL  |
 ------- 

8)、Data Masking Functions 数据脱敏函数

--mask
--将查询回的数据,大写字母转换为X,小写字母转换为x,数字转换为n。
select mask("abc123DEF");
select mask("abc123DEF",'-','.','^'); --自定义替换的字母
0: jdbc:hive2://server4:10000> select mask("abc123DEF");
 ------------ 
|    _c0     |
 ------------ 
| xxxnnnXXX  |
 ------------ 
1 row selected (0.158 seconds)
0: jdbc:hive2://server4:10000> select mask("abc123DEF",'-','.','^'); 
 ------------ 
|    _c0     |
 ------------ 
| ...^^^---  |
 ------------ 

--mask_first_n(string str[, int n]
--对前n个进行脱敏替换
select mask_first_n("abc123DEF",4);

--mask_last_n(string str[, int n])
select mask_last_n("abc123DEF",4);

--mask_show_first_n(string str[, int n])
--除了前n个字符,其余进行掩码处理
select mask_show_first_n("abc123DEF",4);

--mask_show_last_n(string str[, int n])
select mask_show_last_n("abc123DEF",4);

--mask_hash(string|char|varchar str)
--返回字符串的hash编码。
select mask_hash("abc123DEF");
学新通

9)、Misc. Functions 其他杂项函数

--如果你要调用的java方法所在的jar包不是hive自带的 可以使用add jar添加进来
--hive调用java方法: java_method(class, method[, arg1[, arg2..]])
select java_method("java.lang.Math","max",11,22);

--反射函数: reflect(class, method[, arg1[, arg2..]])
select reflect("java.lang.Math","max",11,22);

--取哈希值函数:hash
select hash("alan");

--current_user()、logged_in_user()、current_database()、version()

--SHA-1加密: sha1(string/binary)
select sha1("alan");

--SHA-2家族算法加密:sha2(string/binary, int)  (SHA-224, SHA-256, SHA-384, SHA-512)
select sha2("alan",224);
select sha2("alan",512);

--crc32加密:
select crc32("alan");

--MD5加密: md5(string/binary)
select md5("alan");

0: jdbc:hive2://server4:10000> select java_method("java.lang.Math","max",11,22);
 ------ 
| _c0  |
 ------ 
| 22   |
 ------ 
0: jdbc:hive2://server4:10000> select reflect("java.lang.Math","max",11,22);
 ------ 
| _c0  |
 ------ 
| 22   |
 ------ 
0: jdbc:hive2://server4:10000> select hash("alan");
 ---------- 
|   _c0    |
 ---------- 
| 2996632  |
 ---------- 
0: jdbc:hive2://server4:10000> select sha1("alan");
 ------------------------------------------- 
|                    _c0                    |
 ------------------------------------------- 
| 91e38e63b890fbb214c8914809fde03c73e7f24d  |
 ------------------------------------------- 
0: jdbc:hive2://server4:10000> select md5("alan");
 ----------------------------------- 
|                _c0                |
 ----------------------------------- 
| 02558a70324e7c4f269c69825450cec8  |
 ----------------------------------- 
学新通

3、Hive 用户自定义函数(UDF、UDTF、UDAF)

用户自定义函数简称UDF,源自于英文user-defined function。
根据函数输入输出的行数可以分为3类,分别是:

  • UDF(User-Defined-Function)普通函数,一进一出
  • UDAF(User-Defined Aggregation Function)聚合函数,多进一出
  • UDTF(User-Defined Table-Generating Functions)表生成函数,一进多出
    学新通

1)、示例需求:UDF实现手机号****加密

对于敏感数据往往需要进行脱敏处理。比如手机号

  • 能够对输入数据进行非空判断、手机号位数判断
  • 能够实现校验手机号格式,把满足规则的进行****处理
  • 对于不符合手机号规则的数据直接返回,不处理

2)、UDF实现步骤

  1. 写一个java类,继承UDF,并重载evaluate方法,方法中实现函数的业务逻辑(重载意味着可以在一个java类中实现多个函数功能)
  2. 程序打成jar包,上传HS2服务器本地或者HDFS
  3. 客户端命令行中添加jar包到Hive的classpath: hive>add JAR /xxxx/udf.jar
  4. 注册成为临时函数(给UDF命名):create temporary function 函数名 as ‘UDF类全路径’
  5. HQL中使用函数

3)、pom.xml

<dependencies>
    <dependency>
        <groupId>org.apache.hive</groupId>
        <artifactId>hive-exec</artifactId>
        <version>3.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-common</artifactId>
        <version>3.1.4</version>
    </dependency>
</dependencies>

4)、UDF和GenericUDF实现

UDF函数按照继承类可以分为2种,一个是UDF,一个是GenericUDF,GenericUDF的开发会比UDF复杂一些,一般在以下几种场景下考虑使用GenericUDF:

  • 传参情况复杂
    比如某UDF要传参数有多种数量或多种类型的情况,在UDF中支持这种场景我们需要实现N个不同的evaluate()方法分别对应N种场景的传参,在GenericUDF我们只需在一个方法内加上判断逻辑,对不同的输入路由到不同的处理逻辑上即可。还有比如某UDF参数既要支持String list参数,也要支持Integer list参数。Java不支持同一个方法重载参数只有泛型类型不一样,所以该场景只能用GenericUDF。

  • 需要传非Writable的或复杂数据类型作为参数
    比如嵌套数据结构,传入Map的key-value中的value为list数据类型,或者比如数据域数量不确定的Struct结构,都更适合使用GenericUDF在运行时捕获数据的内部构造

  • 该UDF被大量、高频地使用
    从收益上考虑,会尽可能地优化一切可以优化的地方,则GenericUDF相比UDF在operator中避免了多次反射转化的资源消耗,更适合被考虑

  • 该UDF函数功能未来预期的重构、扩展场景较多,需要做得足够可扩展,则GenericUDF在这方面更优秀

  • UDF

public class EncryptPhoneNumber extends UDF {
    /**
     * 重载evaluate方法 实现函数的业务逻辑
     * @param phoNum  入参:未加密手机号
     * @return 返回:加密后的手机号字符串
     */
    public String evaluate(String phoNum){
        String encryptPhoNum = null;
        //手机号不为空 并且为11位
        if (StringUtils.isNotEmpty(phoNum) && phoNum.trim().length() == 11 ) {
            //判断数据是否满足中国大陆手机号码规范
                String regex = "^(1[3-9]\\d{9}$)";
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(phoNum);
            if (m.matches()) {//进入这里都是符合手机号规则的
                //使用正则替换 返回加密后数据
                encryptPhoNum = phoNum.trim().replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2");
            }else{
                //不符合手机号规则 数据直接原封不动返回
                encryptPhoNum = phoNum;
            }
        }else{
            //不符合11位 数据直接原封不动返回
            encryptPhoNum = phoNum;
        }
        return encryptPhoNum;
    }
}


学新通
  • GenericUDF
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
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.JavaStringObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;

public class EncryptPhoneNumber extends GenericUDF {
	StringObjectInspector elementOI;
	/**
	 * Initialize this GenericUDF. This will be called once and only once per
	 * GenericUDF instance.
	 */
	@Override
	public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
		// 1. 检查该记录是否传过来正确的参数数量
		if (arguments.length != 1) {
			throw new UDFArgumentException("输入参数错误,必须是一个参数。");
		}
		// 2. 检查该条记录是否传过来正确的参数类型
		ObjectInspector a = arguments[0];
		if (!(a instanceof StringObjectInspector)) {
			throw new UDFArgumentException("輸入參數錯誤,需要是一個字符串");
		}

		// 3. 检查通过后,将参数赋值给成员变量ObjectInspector,为了在evaluate()中使用
		this.elementOI = (StringObjectInspector) a;
		return PrimitiveObjectInspectorFactory.javaStringObjectInspector;
	}

	/**
	 * Evaluate the GenericUDF with the arguments. 重载evaluate方法 实现函数的业务逻辑
	 */
	@Override
	public Object evaluate(DeferredObject[] arguments) throws HiveException {
		String phoNum = elementOI.getPrimitiveJavaObject(arguments[0].get()).toString();
		String encryptPhoNum = null;
		// 手机号不为空 并且为11位
		if (StringUtils.isNotEmpty(phoNum) && phoNum.trim().length() == 11) {
			// 判断数据是否满足中国大陆手机号码规范
			String regex = "^(1[3-9]\\d{9}$)";
			Pattern p = Pattern.compile(regex);
			Matcher m = p.matcher(phoNum);
			if (m.matches()) {// 进入这里都是符合手机号规则的
				// 使用正则替换 返回加密后数据
				encryptPhoNum = phoNum.trim().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
			} else {
				// 不符合手机号规则 数据直接原封不动返回
				encryptPhoNum = phoNum;
			}
		} else {
			// 不符合11位 数据直接原封不动返回
			encryptPhoNum = phoNum;
		}
		return encryptPhoNum;
	}

	/**
	 * Get the String to be displayed in explain.
	 */
	@Override
	public String getDisplayString(String[] children) {
		return "this is a EncryptPhoneNumber pro.";
	}

	public static void main(String[] args) throws Exception {
		EncryptPhoneNumber ep = new EncryptPhoneNumber();
		JavaStringObjectInspector stringOI = PrimitiveObjectInspectorFactory.javaStringObjectInspector;

		JavaStringObjectInspector resultInspector = (JavaStringObjectInspector) ep.initialize(new ObjectInspector[] { stringOI });

		Object result = ep.evaluate(new DeferredObject[] { new DeferredJavaObject("13917885967") });
		System.out.println("result:"   result);
	}

}
学新通

5)、打包

mvn package clean -Dmaven.test.skip=true

mvn package -Dmaven.test.skip=true

6)、添加jar包到Hive的classpath

0: jdbc:hive2://server4:10000> add jar /usr/local/bigdata/hive-0.0.1-SNAPSHOT.jar;
No rows affected (0.01 seconds)

7)、注册成为临时函数

create temporary function 函数名 as 'UDF类全路径';

create temporary function encryptPhoneNumber as 'org.hive.udf.EncryptPhoneNumber';

0: jdbc:hive2://server4:10000> create temporary function encryptPhoneNumber as 'org.hive.udf.EncryptPhoneNumber';
No rows affected (0.023 seconds)

8)、验证

0: jdbc:hive2://server4:10000> select encryptPhoneNumber("13788889999");
 -------------- 
|     _c0      |
 -------------- 
| 137****9999  |
 -------------- 

以上,完成了hive shell客户端的属性配置、内置运算符和函数的介绍及使用示例。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhiafiib
系列文章
更多 icon
同类精品
更多 icon
继续加载