0


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

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;--查看运算符或者函数的使用说明describefunction count;--使用extended 可以查看更加详细的使用说明describefunctionextended 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表完成运算符、函数功能测试
select1+1 from dual;select1+1;
  • 示例
----------------Hive中关系运算符----------------------------is null空值判断select1from dual where'itcast'isnull;--is not null 非空值判断select1from dual where'itcast'isnotnull;--like比较: _表示任意单个字符 %表示任意数量字符--否定比较: NOT A like Bselect1from dual where'itcast'like'it_';select1from dual where'itcast'like'it%';select1from dual where'itcast'notlike'hadoo_';select1from dual wherenot'itcast'like'hadoo_';--rlike:确定字符串是否匹配正则表达式,是REGEXP_LIKE()的同义词。select1from dual where'itcast'rlike'^i.*t$';select1from dual where'123456'rlike'^\\d+$';--判断是否全为数字select1from dual where'123456aa'rlike'^\\d+$';--regexp:功能与rlike相同 用于判断字符串是否匹配正则表达式select1from dual where'itcast'regexp'^i.*t$';

2、算术运算符及示例

-------------------Hive中算术运算符-----------------------------------取整操作: div  给出将A除以B所得的整数部分。例如17 div 3得出5。select17div3;--取余操作: %  也叫做取模mod  A除以B所得的余数部分select17%3;--位与操作: &  A和B按位进行与操作的结果。 与表示两个都为1则结果为1select4&8from dual;--4转换二进制:0100 8转换二进制:1000select6&4from dual;--4转换二进制:0100 6转换二进制:0110--位或操作: |  A和B按位进行或操作的结果  或表示有一个为1则结果为1select4|8from dual;select6|4from dual;--位异或操作: ^ A和B按位进行异或操作的结果 异或表示两者的值不同,则结果为1select4^8from dual;select6^4from dual;

3、逻辑运算符及示例

--3、Hive逻辑运算符--与操作: A AND B   如果A和B均为TRUE,则为TRUE,否则为FALSE。如果A或B为NULL,则为NULL。select1from dual where3>1and2>1;--或操作: A OR B   如果A或B或两者均为TRUE,则为TRUE,否则为FALSE。select1from dual where3>1or2!=2;--非操作: NOT A 、!A   如果A为FALSE,则为TRUE;如果A为NULL,则为NULL。否则为FALSE。select1from dual wherenot2>1;select1from dual where!2=1;--在:A IN (val1, val2, ...)  如果A等于任何值,则为TRUE。select1from dual where11in(11,22,33);--不在:A NOT IN (val1, val2, ...) 如果A不等于任何值,则为TRUEselect1from dual where11notin(22,33,44);--逻辑是否存在: [NOT] EXISTS (subquery)--将主查询的数据,放到子查询中做条件验证,根据验证结果(TRUE 或 FALSE)来决定主查询的数据结果是否得以保留。select A.*from A
whereexists(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");--字符串反转函数:reverseselect reverse("angelababy");--字符串连接函数:concat(str1, str2, ... strN)--字符串转大写函数:upper,ucaseselect upper("angelababy");selectucase("angelababy");--字符串转小写函数:lower,lcaseselect lower("ANGELABABY");selectlcase("ANGELABABY");--去空格函数:trim 去除左右两边的空格select trim(" angelababy ");--左边去空格函数:ltrimselect ltrim(" angelababy ");--右边去空格函数:rtrimselect rtrim(" angelababy ");--空格字符串函数:space(n) 返回指定个数空格select space(4);--重复字符串函数:repeat(str, n) 重复str字符串n次selectrepeat("angela",2);--首字符ascii函数:asciiselect ascii("angela");--a对应ASCII 97--左补足函数:lpadselect lpad('hi',5,'??');--???hiselect lpad('hi',1,'??');--h--右补足函数:rpadselect rpad('hi',5,'??');--集合查找函数: find_in_set(str,str_array)select find_in_set('a','abc,b,ab,c,def');

2)、Date Functions 日期函数

--获取当前日期: current_dateselectcurrent_date();--获取当前时间戳: current_timestamp--同一查询中对current_timestamp的所有调用均返回相同的值。selectcurrent_timestamp();--获取当前UNIX时间戳函数: unix_timestampselect unix_timestamp();--日期转UNIX时间戳函数: unix_timestampselect unix_timestamp("2022-10-21 17:47:21");--指定格式日期转UNIX时间戳函数: unix_timestampselect unix_timestamp('20221021 17:47:21','yyyyMMdd HH:mm:ss');--UNIX时间戳转日期函数: from_unixtimeselect 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-0100: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_addselect date_add('2022-9-21',10);0: jdbc:hive2://server4:10000> select date_add('2022-9-21',10);+-------------+|     _c0     |+-------------+|2022-10-01|+-------------+--日期减少函数: date_subselect date_sub('2022-10-01',10);--抽取日期函数: to_dateselect to_date('2022-10-21 17:47:21');--日期转年函数: yearselectyear('2022-10-21 17:47:21');--日期转月函数: monthselectmonth('2022-10-21 17:47:21');--日期转天函数: dayselectday('2022-10-21 17:47:21');--日期转小时函数: hourselecthour('2022-10-21 17:47:21');--日期转分钟函数: minuteselectminute('2022-10-21 17:47:21');--日期转秒函数: secondselectsecond('2022-10-21 17:47:21');--日期转周函数: weekofyear 返回指定日期所示年份第几周select weekofyear('2022-10-21 17:47:21');

3)、Mathematical Functions 数学函数

--取整函数: round  返回double类型的整数值部分 (遵循四舍五入)selectround(3.1415926);--指定精度取整函数: round(double a, int d) 返回指定精度d的double类型selectround(3.1415926,4);--向下取整函数: floorselect floor(3.1415926);select floor(-3.1415926);--向上取整函数: ceilselect 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);--绝对值函数: absselect 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 limit3;describefunctionextended isnull;--if条件判断: if(boolean testCondition, T valueTrue, T valueFalseOrNull)selectif(1=2,100,200);select*,if(sex ='男','M','W')from student limit3;0: jdbc:hive2://server4:10000> select if(sex ='男','M','W') from student limit 3;+------+| _c0  |+------+| M    || W    || W    |+------+3rows 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,那么返回NULLselectCOALESCE(null,11,22,33);selectCOALESCE(null,null,null,33);selectCOALESCE(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] ENDselectcase100when50then'tom'when100then'mary'else'tim'end;selectcase sex when'男'then'male'else'female'endfrom student limit3;select*,case sex 
        when'男'then'male'else'female'endfrom student limit3;0: jdbc:hive2://server4:10000> select case sex when '男' then 'male' else 'female' end from student limit 3;+---------+|   _c0   |+---------+| male    || female  || female  |+---------+3rows 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,否则返回一个selectnullif(11,11);selectnullif(11,12);--assert_true(condition)--如果'condition'不为真,则引发异常,否则返回nullSELECT assert_true(11>=0);SELECT assert_true(-1>=0);

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

--任意数据类型之间转换:castselect cast(12.14asbigint);select cast(12.14as string);select cast("hello"asint);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  |+------------+1row 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);--取哈希值函数:hashselecthash("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
publicclassEncryptPhoneNumberextends UDF {/**
     * 重载evaluate方法 实现函数的业务逻辑
     * @param phoNum  入参:未加密手机号
     * @return 返回:加密后的手机号字符串
     */publicStringevaluate(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
importjava.util.regex.Matcher;importjava.util.regex.Pattern;importorg.apache.commons.lang3.StringUtils;importorg.apache.hadoop.hive.ql.exec.UDFArgumentException;importorg.apache.hadoop.hive.ql.metadata.HiveException;importorg.apache.hadoop.hive.ql.udf.generic.GenericUDF;importorg.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;importorg.apache.hadoop.hive.serde2.objectinspector.primitive.JavaStringObjectInspector;importorg.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;importorg.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;publicclassEncryptPhoneNumberextendsGenericUDF{StringObjectInspector elementOI;/**
     * Initialize this GenericUDF. This will be called once and only once per
     * GenericUDF instance.
     */@OverridepublicObjectInspectorinitialize(ObjectInspector[] arguments)throwsUDFArgumentException{// 1. 检查该记录是否传过来正确的参数数量if(arguments.length !=1){thrownewUDFArgumentException("输入参数错误,必须是一个参数。");}// 2. 检查该条记录是否传过来正确的参数类型ObjectInspector a = arguments[0];if(!(a instanceofStringObjectInspector)){thrownewUDFArgumentException("輸入參數錯誤,需要是一個字符串");}// 3. 检查通过后,将参数赋值给成员变量ObjectInspector,为了在evaluate()中使用this.elementOI =(StringObjectInspector) a;returnPrimitiveObjectInspectorFactory.javaStringObjectInspector;}/**
     * Evaluate the GenericUDF with the arguments. 重载evaluate方法 实现函数的业务逻辑
     */@OverridepublicObjectevaluate(DeferredObject[] arguments)throwsHiveException{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.
     */@OverridepublicStringgetDisplayString(String[] children){return"this is a EncryptPhoneNumber pro.";}publicstaticvoidmain(String[] args)throwsException{EncryptPhoneNumber ep =newEncryptPhoneNumber();JavaStringObjectInspector stringOI =PrimitiveObjectInspectorFactory.javaStringObjectInspector;JavaStringObjectInspector resultInspector =(JavaStringObjectInspector) ep.initialize(newObjectInspector[]{ stringOI });Object result = ep.evaluate(newDeferredObject[]{newDeferredJavaObject("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客户端的属性配置、内置运算符和函数的介绍及使用示例。

标签: hive hadoop 大数据

本文转载自: https://blog.csdn.net/chenwewi520feng/article/details/131080242
版权归原作者 一瓢一瓢的饮 alanchan 所有, 如有侵权,请联系我们删除。

“7、hive shell客户端与属性配置、内置运算符、函数(内置运算符与自定义UDF运算符)”的评论:

还没有评论