2020.9.27(Hive Serde、HiveServer2、Hive函数)

回顾:上节课讲了hive的基本语句,DDL,DML
和MySQL差不多,但是也有一些自己独特的东西,比如在定义一张表的时候需要指定行格式。
这节课开始,hive的点就比较琐碎了。

Hive Serde

在这里插入图片描述
Hive SerDe - Serializer and Deserializer –SerDe 用于做序列化和反序列化。
什么意思?
hive在运行过程中,数据是存储在hdfs的,但是执行引擎是mapreduce,这两个之间有必然的关系么?
写的都是SQL语句,可以通过load的方式加载数据,也可以直接向hdfs里面上传数据文件。也可以读取进来,原因hive是读时检查,只要读取的数据文件,或指定的数据目录有数据文件,就可以把数据读进来。如果符合格式就正常显示,不符合格式就显示为null。这是正常的状态。
但是除此之外,如果遇到比较复杂的情况,数据里面包含int,String,Array,Map类型,这时候,Array里面能嵌套Map么?Map里面能嵌套Array么?
可以的。
在这里插入图片描述
data_type既包含了基本类型,又包含了复杂的类型,所以当表格嵌套非常复杂的情况,再使用ROW FORMAT row_format fields , collection items , map keys这样的方式来做分割的话可能就无法生效了。因此在这种形式后面个serde可以完成对应的行格式的解析的需求

row_format
  : DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char]
        [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
        [NULL DEFINED AS char]   -- (Note: Available in Hive 0.13 and later)
  | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]

具体需求:
在这里插入图片描述
想把这样的数据进行存储,但是时间字段前后的中括号没有实际意义,要求过滤掉中括号。请求有双引号,也要求过滤掉,最终在hive里面查看的时候没有中括号,没有双引号,该怎么实现。
最好的方式是使用正则表达式
在这里插入图片描述

"([^ ]*) ([^ ]*) ([^ ]*) \\[(.*)\\] \"(.*)\" (-|[0-9]*) (-|[0-9]*)"
([^ ]*)
^在中括号里表示取反,后面一个空的字符串,表示非空。
 \\[(.*)\\]
 表示要匹配中括号这个值了,里面是.*表示中括号里面所有字符留下,中括号不要
 \"(.*)\" 
 过滤双引号
 (-|[0-9]*)
 表示-或者09,任意数字,任意位数

这时候打开hive:
首先先把hive的元数据服务启动好:

hive --service metastore

打开hive的客户端,每次启动的时候比较慢,原因是什么?hive是需要连接到hdfs的,连接过程是比较浪费时间的。
在hive里执行语句:

CREATE TABLE logtbl ( 
host STRING,
identity STRING,
t_user STRING,
time STRING,
request STRING,
referer STRING,
agent STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
"input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) \\[(.*)\\] \"(.*)\" (-|[0-9]*) (-|[0-9]*)")
STORED AS TEXTFILE

该load数据文件了

load data local inpath "/root/data/log" into table logtbl;
select * from tbl;

中括号和双引号都没有了,因为匹配规则的时候匹配掉了。
这两种方式的应用场景分别是什么?
如果数据是规范化格式化的文件的话,不包含很多嵌套关系的话,就用之前的方式,如果数据结构比较复杂,包含了N多层的Array,Map的嵌套,推荐使用serde方式

HiveServer2 与函数操作

hive搭建成功后,在使用jdbc的方式访问hive的时候,并不能够访问成功,为什么?总是报连接拒绝的错误。
原因:jdbc在使用连接的时候,不能用之前的安装方式,需要换另外一种安装方式了。

HiveServer2是什么?

先打开两个页面

1.进入HIVE的HOME页面,找到HiveServer2: Overview, HiveServer2 Client and Beeline, Hive Metrics打开,找到HiveServer2也打开。

第一个印象,为什么叫hiveserver2,不叫hiveserver1?

HiveServer2 (HS2) is a server interface that enables remote clients to execute queries against Hive and retrieve the results (a more detailed intro here). The current implementation, based on Thrift RPC, is an improved version of HiveServer and supports multi-client concurrency and authentication. It is designed to provide better support for open API clients like JDBC and ODBC.
HiveServer2 (HS2)是一个服务接口,允许远程客户端去执行SQL语句,依托于hive,来检索对应的数据。(现在如果一个远程机,比如虚拟机是放在互联网环境里的,现在想连接需要开启一个hiveserver2的方式来检索数据)
当前版本的实现是基于Thrift RPC,(在连接元数据的时候也用到了Thrift RPC这个服务),对于hiveserver是一个提升的版本。
在安装目录下:
在这里插入图片描述
有hiveserver2,没有hiveserver已经完全被淘汰了,打开官网hiveServer页面
Thrift Hive Server

HiveServer is an optional service that allows a remote client to submit requests to Hive, using a variety of programming languages, and retrieve results. HiveServer is built on Apache ThriftTM (http://thrift.apache.org/), therefore it is sometimes called the Thrift server although this can lead to confusion because a newer service named HiveServer2 is also built on Thrift. Since the introduction of HiveServer2, HiveServer has also been called HiveServer1.
HiveServer 是一个可选的服务,允许一个远程的客户端去提交请求到hive(每一时刻只能有一个客户端进行访问),问题很大,并发受限。
在一个公司里面用hive的人只有一个开发程序员么?数据分析师。包括运营人员,推广人员,如果需要公司的历史数据,也是要做分析的。
同一时刻可能会有N多个用户,同时去访问对应的hive,这时候用hiveserver无法保证。
HiveServer2 (HS2) is a server interface that enables remote clients to execute queries against Hive and retrieve the results (a more detailed intro here). The current implementation, based on Thrift RPC, is an improved version of HiveServer and supports multi-client concurrency and authentication. It is designed to provide better support for open API clients like JDBC and ODBC.
hiveserver2支持多客户端并发访问和认证,这个目的是为了提供更好的支持给openAPI例如JDBC和ODBC的方式。所以hiveserver2在公司里用的是比较多的。

启动hiveServer2

两种方式:

$HIVE_HOME/bin/hiveserver2
hive --service hiveserver2

hiveserver2相当于是一个服务端,但是是针对用户来说,此时也需要连接到元数据服务。node03正开启着元数据服务能不能停掉?
可以的。
启动好之后注意了,这个窗口也是一个阻塞式窗口,同时提供了对外访问的端口号。比如MySQL想对外连接是开放了3306的端口对外部进行连接,这里也是一样的

ss -nal

找一下有没有10000,10000是hiveserver2默认的值:
在这里插入图片描述
用来保证远程的连接,开启这个服务之后,就可以进行最基本的远程连接了。
注意:在hadoop里面有个相似端口10020,在hadoop里面每次提交很多MR任务,MR任务在执行过程中一定保留了执行日志,这些日志在下次重新启动集群的时候,数据还在么?比如MapTask多少个,运行多少时间,ReduceTask多少个,运行多少时间。每次重启之后就没有了。
这个端口是历史日志服务器的端口,这个地方需要进行单独的配置的。

mr-jobhistory-demon.sh start historyserver

需要配置参数,指定具体哪一台机器。执行这个命令,可以把执行MR任务当做一个文件保存到hdfs里面。重启集群hdfs里的数据是不会丢的,下次重启集群的时候,数据还在,还可以看历史的任务。
看历史任务的意义:分析哪些任务执行比较慢,哪些任务执行比较快。发生在什么地方数据量比较大可以做统计。
一般来说是需要进行配置的,而且在某些服务里面,需要MR执行环境的话,也是必须要开启历史日志服务器的,因为一个需求需要N个MR的迭代过程,实现的时候,前一个MR的输出作为后一个MR的输入,需要了解之前允许的状态。

10002端口也是一个web访问的端口,是可以进行访问的。
http://192.168.237.100:10002
提供了hiveserver2的webUI,活跃的会话,执行的query语句,最近关闭的25个query语句,以及一些属性,都可以进行直观显示。但是不启动hiveserver2是没有的,这个端口不能被访问。

在这里插入图片描述
启动了hiveserver2不需要再启动metaserver了么?在企业里hiveserver2是如何使用的?

对于hiveserver2来说,匹配的客户端工具不叫hive了,而叫hiveserver2

Beeline – Command Line Shell

HiveServer2 supports a command shell Beeline that works with HiveServer2. It’s a JDBC client that is based on the SQLLine CLI (http://sqlline.sourceforge.net/). There’s detailed documentation of SQLLine which is applicable to Beeline as well.
hiverserver2支持一个命令行shell,Beeline是和hiveserver2一起工作的,它是一个jdbc的客户端,依赖于SQL的命令行

beeline
!connect jdbc:hive2://hadoop100:10000/default root ok

登陆失败
Failed to open new session:
User: root is not allow to impersonate root (state=08501,code0)
root不能被伪装成root
在做之前需要做一件事情:当第一次运行的时候,没有修改任何配置,hadoop里面权限管理的机制。
打开hadoop的官网,http://hadoop.apache.org/old/找到对应的版本,Documentation->Release 2.6.5,在左边栏目找到Superusers
In this example super’s kerberos credentials are used for login and a proxy user ugi object is created for joe. The operations are performed within the doAs method of this proxy user ugi object.
The superuser must be configured on namenode and jobtracker to be allowed to impersonate another user. Following configurations are required.
kerberos ,如果现在作为一个用户想要调用服务了,这时候必须要进行配置:
在之前如果接触过hive并且用的1.x的版本,不需要配置这个属性都可以直接连接,但是2.x的时候不可以了。因为1.x调用的是老的api,2.x调用的是新的api,在hadoop里面有两个api
一个叫mapred
一个叫mapreduce
有两套以包名区分的api,在2.x的时候使用的是mapreduce这个新的api,在这个api里面规定了,必须要进行伪装。
需要把配置加到配置项里,变成一个superuser这时候才可以成功。
在hadoop的core-site.xml添加属性,为了安全,hadoop里面有一句话叫做防止好人做错事,而不是阻止坏人做坏事(hadoop的权限控制和没有设置一样,在Windows里面想操作hdfs只要把用户改成root就可以随便操作了,如果没有用户系统,不建-user用户目录的话,只要伪装成是root都可以做了,如果公司数据安全比较高的话会用kerberos 配置,但也会导致访问非常麻烦,需要很多的权限认证):

   <property>
     <name>hadoop.proxyuser.super.groups</name>
     <value>group1,group2</value>
     <description>Allow the superuser super to impersonate any members of the group group1 and group2</description>
   </property>
   <property>
     <name>hadoop.proxyuser.super.hosts</name>
     <value>host1,host2</value>
     <description>The superuser can connect only from host1 and host2 to impersonate a user</description>
   </property>

不停止集群的方式:

   <property>
     <name>hadoop.proxyuser.root.groups</name>
     <value>*</value>
   </property>
   <property>
     <name>hadoop.proxyuser.root.hosts</name>
     <value>*</value>
   </property>

xml配置文件里的root不是随便写的,你是哪一个用户就写谁。把root设置成超级管理员,这样认证的时候就没有问题了,然后分别发送到node02,node03,node04
这还没完,执行下面的命令,在node01执行:

bin/hdfs dfsadmin -fs hdfs://node01:8020 -refreshSuperUserGroupsConfiguration

需要在两台namenode节点里执行进行修改,在node02里执行:

bin/hdfs dfsadmin -fs hdfs://node02:8020 -refreshSuperUserGroupsConfiguration

注意:beeline里面,命令前要加感叹号!
这时候再重新进入beeline:

beeline
!connect jdbc:hive2://hadoop100:10000/default root ok

连接成功了。root是整个系统的超级用户了。

show tables;
select * from psn;

表也可以查询成功了,可以进行基本操作了。
解释root ok 。
如果想仿照jdbc的方式连接MySQL数据库,必须要配置用户名和密码,但现在hive没有进行过类似的配置,这里没什么用,因为hiveserver2默认是不进行认证的,故意写的和MySQL一样。
这个beeline不需要连接到MySQL,只要能保证连接到10000端口就可以了
所有可以这样写:

!close
! connect jdbc:hive2://node03:10000/default ChaokeaiMuzhi qwer

在这里插入图片描述
用指定的用户去访问/tmp目录,没有对应的权限了,非常好解决,给这个用户权限。
/tmp指的是hdfs的目录:
在这里插入图片描述不允许进行基本访问操作的。
需要做一些修改:

hdfs dfs -chmod 777 /tmp

这时候就可以正常运行了。
刚才是第一种方式使用的是!close的方式,退出当前会话,还有种简单方式

!quit

表示退出beeline

beeline -u jdbc:hive2://node03:10000/default

也能够操作成功。
如果在beeline里面直接加参数也是ok的
在hiveserver2里面用户名和密码是无效的和没有一样。
在这里插入图片描述在企业里用户名和密码如果想生效的话是需要进行单独配置的,但这个时候要思考问题,企业里如果要接受大量数据,每次请求数据都要用户名和密码,无形中增加了操作复杂度浪费时间。hive是在内网而不是在外网中使用的,不是给用户而是给程序员使用的。

为什么不直接集成在hive中还要开发hiveserver关联hive依赖?
如果有了hive窗口之后可以进行基本操作,但这样做会有一个问题,如果是刚进来的小白,一开始就这样的窗口,不知道写什么东西。如果能把它集成成一个web的浏览器,直接在浏览器里写SQL语句,写完提交运行结果用户体验度更好。官网也推荐使用hiveserver2

hive客户端命令行是给开发者使用的,而hiveserver2是给数据分析师等其他用户来操作的,hiveserver2可以包装成程序远程调用。

还有一个好处:

load data local inpath '/root/data/data' into table psn;

Error: Error while compiling statement: FAILED: SemanticException Line 1:23 Invalid path ''/root/data/data'': No file matching path file:/root/data/data (state=42000,code=40000)
在一般情况下不能进行增删改操作的,只能进行查询,是给查询用户使用的,如果要让他生效也行,当前路径必须要配置在服务端而不可以在客户端。
如果用户大部分都是查询需求的话,建议使用hiveserver2,可以屏蔽掉增删改的操作

在企业里是怎么做的,官网里有这样一句话,非常非常关键
在这里插入图片描述Remote HiveServer2 mode is recommended for production use, as it is more secure and doesn’t require direct HDFS/metastore access to be granted for users.

远程hiveserver2的方式更加推荐使用在生产环境里,因为它更加安全,并且不会要求我们直接访问hdfs/metastore的元数据,数据安全更加有保证了。

我们刚刚的模式并不是企业里用的最多的模式。

提问:hive的业务场景
hive的业务场景:电商公司有很多的产品,提供了很多的对外服务,比如商品服务,购物车服务, 派单服务,这些服务都有数据的,这时候需要对历史数据做分析MySQL可以做么?或者电商要统计过去十年以来在八月份做推广活动和销售额之间的对比关系。数量非常庞大,不可能一直在MySQL里存着。数据规模大之后查询非常慢,在用关系型数据库的时候做读写分离,分库分表,为了提高查询效率。但是像这种历史分析的,不需要在很短的时间内达到效果,这时候完全可以使用hive来做。Hive的本质就是OLAP。

提问:ES可以代替hive么?
ES重点是做基本的检索的服务,而hive是做数据的整体分析,比如需要表关联操作,ES比较麻烦但hive是可以实现的,因为SQL语句里有join的语法。

在企业里hive的数据是不可以丢的。hive的数据是放在hdfs,hdfs是非常可靠的,如果公司用的云主机/云服务,有一些固定的存储引擎,比如AWS在使用的时候,有S3的存储机制,是全球性的存储服务,默认帮你把数据保存了8份。在运维人员那边有数据不可丢的限制,几乎不会丢。

面试中描述数据量的问题:
数据量的问题,要从两个层面来描述:
1.数据的大小:比如GB TB PB级别
2.数据的条数:比如一条记录如果是0.5kb,即使1000w条记录也没多大,如果一条记录10kb,1000w条非常大了。

付款信息这些一定是要放在关系型数据库里面的。因为要求在很短的时间内做出响应。但最终如果有很多历史数据要做分析的话,可以把MySQL的数据迁移到hdfs里面,比如Sqoop或者阿里的Datax就是专门用来做关系型数据库和大数据平台的数据迁移。

继续讲hiveserver2,官网里推荐的是remote hiveserver2的方式,什么叫remote hiveserver2?
刚刚是在第三台机器里启动的hiveserver2,在第四台里通过beeline的方式进行访问,这样的方式有什么不好的地方。第三台hiveserver2在启动的时候其实也启动了一个类似metastore的服务,这种方式不太好,最好能把它当成一个单独的服务,能供其他组件,其他任何服务使用。这个时候可以参考另外一种方式:
把第三台hiveserver2关掉,启动hive --service metastore
在第四台开两个session,第一个敲hive进入hive的命令行,在这个命令行里可以进行增删改查的基本操作
在第二个session里同时启动一个hiveserver2。意味着可以同时给程序员操作,也开放了10000端口号
此时,只要能保证10000端口号能被访问到,就可以进行基本的连接了。
意味着:元数据还在第三台,第四台既可以做hive的命令行,又可以做hive的hiveserver2服务。
此时再开一个node04可以写:beeline -u jdbc:hive2://node04:10000/default
这里也是可以进行请求访问的。
什么意思?
在node04里,hive命令行和hiveserver2共用了一个元数据服务,在企业里元数据服务是必须启动的。在第四台里又可以做hive客户端,又可以做hiveserver2。
同样在node02里,进行重新连接:

beeline -u jdbc:hive2://node04:10000/default

这时候也可以进行基本的连接。这是在企业里面用的相对比较多的方式。
也就是说:这个hive命令行是给程序员使用的,而node04的10000端口,是给所有的查询工程师用的。如果有查询需求使用beeline,如果有增删改交给程序员用hive命令行的方式进行操作。
这才是公司里使用比较多的方式,推荐使用。元数据实现的共享操作,之后有其他组件,其他框架,其他服务,也可以直接来操作。

hiveserver2是怎么 连接到元数据的?
不管hive还是hiveserver2都可以看一个东西。

cd /opt/hive/bin
cat hive

可以查看hive的脚本
首先会先执行hive-config.sh的配置文件 ->会读取配置文件,在node04里只配置了一个thrift的9083,所有这时候会通过9083访问到元数据来进行一个配置,不管hive还是hiveserver2都必须读取配置文件。

现在在node04启动了hiveserver2的服务,无论是beeline还是别的其实是提供了一个jdbc的访问方式,此时能否通过jdbc来操作hive呢?
是可以的。

怎么做???

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class HiveJdbcClient {
    
    

	private static String driverName = "org.apache.hive.jdbc.HiveDriver";

	public static void main(String[] args) throws SQLException {
    
    
		try {
    
    
			Class.forName(driverName);
		} catch (ClassNotFoundException e) {
    
    
			e.printStackTrace();
		}

		Connection conn = DriverManager.getConnection("jdbc:hive2://node04:10000/default", "root", "");
		Statement stmt = conn.createStatement();
		String sql = "select * from psn limit 5";
		ResultSet res = stmt.executeQuery(sql);
		while (res.next()) {
    
    
			System.out.println(res.getString(1) + "-" + res.getString("name"));
		}
	}
}

打开idea,写了一个HiveDemo的案例,非常简单,里面就写了两个东西,一个HiveJdbcClient
第一步:driverName = “org.apache.hive.jdbc.HiveDriver”
第二步:Class.forName(driverName); 加载对应的驱动
第三步:Connection conn = DriverManager.getConnection(“jdbc:hive2://node04:10000/default”, “root”, “”); 获取连接
第四步:写SQL语句查询:String sql = “select * from psn limit 5”;
第五步:打印查询结果

所以在代码里面也可以操纵hive,jdbc就是这样的功能。
mybatis能连接hive么?没有试过。理论上是没有问题的,只要是jdbc就能操作。

无论是jdbc还是beeline做的什么事情?
写完sql语句了,把sql语句提交给对应的hivedriver,hivedriver执行完成之后,把结果再返回给客户端。就这样一件事情,不能上传文件。

注意:Class.forName(driverName); 加载对应的驱动,意味着需要对应的jar包
在node02中,cd /opt/hive/lib目录里,有很多jar包,ll ./ wc看到有255个jar包, 可以用maven的方式,最省事的方式是把对应的jar包都拷贝过来。

Hive函数

在MySQL、Oracle里面是否用过函数?用的最多的叫聚合函数。
聚合函数也比较好理解,比如count(),sum(),avg(),max()这种,在对应的hive里面都是有这些函数的。
在node04的hive命令行里进行操作:

select count(*) from psn;

开始执行MR任务了,会得到对应结果。
怎么看这些东西,还是找官方文档,第一手的学习资料。

提问:row_number() over()是什么?
表示开窗函数,是精简化的sql的操作。MySQL里面到8以后才进行支持。但hive里面是支持对应的开窗函数的操作的,包括后面学的sparkSQL也是支持的。开窗函数后面用的还是比较多的,讲spark的时候再学。

看官网:找UDF
在这里插入图片描述

Operators and UDFs:

包含了一些操作符和UDF函数,大部分都和MySQL一样
在这里插入图片描述在这里插入图片描述在这里插入图片描述
什么意思?
比如在我们的数据表中:
在这里插入图片描述这张表里有爱好有地址,想取到对应的book怎么取?

select likes[1] from psn;

用类似于去数据的方式根据下标来把值取出来。

kv键值对怎么取?

select address["beijing"] from psn;

也可以把后面值取出来,和Java里的操作几乎一模一样的。

sturct相当于Java里的类,通过.的方式来取就可以了。
官网里都有明确解释,看官网直接学就完事了。

hive里提供了非常丰富的函数支持,可以拿函数来做很多事情。这些东西都是hive自带的,不需要相关配置,如果有需求的话,直接调里面函数就可以了。而不需要自己写非常复杂的逻辑了。
这是数字函数和MySQL、Oracle一模一样没什么区别。
Collection Functions 集合函数:
用的比较多的size(),map_keys(),map_values()
可以返回对应的key value 和 size

select size(likes) from psn; 

关系型数据库里不支持集合类型,但是hive支持,可以直接把值取出来。其实在实际工作中用的非常少,几乎不用。
Type Conversion Functions 类型转换函数

select cast("1" as int) from psn;

可以把值转成最基本的int类型,但是注意了,如果写"abc"会显示null,因为abc并不能转成int类型的值。
只需要熟悉就可以了,知道有这些函数就可以了,怎么用,需要的时候来查都来得及。

再往下看:
Date Functions 日期函数
也非常多,有格式化日期操作,返回年,季度,月,天,时,分,秒很多的值,weekofyear一年中的第几周,datediffdate之间的差值,date_add在某个date上面添加一个时间,date_sub减去一个时间,有很多的基本操作。自己练演示没啥意义,自己练,看一遍又忘记了。

Conditional Functions 条件函数

什么叫条件函数?
如果公司里面用的是Oracle的话,在用case when的时候,decode的时候,用的是相对而言比较多的,条件函数适合用于什么场景?
在公司里面有一个非常重要的东西叫做行转列
举个例子:
有这么一张表:

name subject score
zs yuwen 78
zs shuxue 78
zs yingyu 78
ls yuwen 78
ls shuxue 78
ls yingyu 78
ww yuwen 78
ww shuxue 78
ww yingyu 78

要求改成:

name yuwen shuxue yingyu
zs 78 78 78
ls 78 78 78
ww 78 78 78

这种业务需求见过没?
这种需求用的非常非常多!!!!有N多种实现方式
第一种:join
第二种:union all
第三种:case when
第四种:decode
第五种:条件函数

需要把列值当成行字段了,

select name,score from t where t.subject="yuwen"; t1
select name,score from t where t.subject="shuxue"; t2
select name,score from t where t.subject="yingyu"; t3

select t1.name,t1.score,t2.score,t3.score from t1 join t2 on t1.name=t2.name join t3 on t1.name=t3.name

这样一定可以完成需求,要使用n多次的join效率不太高。
其他的实现方式不演示了。

case when的实现方式:

select t.name,case t.subject when "yuwen" end ,case t.subject when "shuxue" end,

类似这样的方式也能完成对应的需求操作,就是这样一个实现,并不是特别难。
做大数据之后也是天天写sql,避免不了的,因为sql最高效。

String Functions字符串函数
比如concat进行字符串连接,field获取里面的属性,length长度,lower小写,trim去重空格,和Java里面的string类型时一模一样的

看最关键的:

array split(string str, string pat) Splits str around pat (pat is a regular expression).

split函数,可以用来切割。切割完成之后返回的是array对象,重点留意。

Built-in Aggregate Functions (UDAF)聚合函数
count(*), count(expr), count(DISTINCT expr[, expr…])
sum(col), sum(DISTINCT col)
avg(col), avg(DISTINCT col)
min(col)
max(col)
这五个用的比较多,但除此之外,还有一些平方根,方差,样本方差,相关系数,也帮我们做了封装
variance(col), var_pop(col)
var_samp(col)
stddev_pop(col)
stddev_samp(col)
covar_pop(col1, col2)
covar_samp(col1, col2)
corr(col1, col2)
percentile(BIGINT col, p)
知道做什么用的就可以了

Built-in Table-Generating Functions (UDTF)

UDTF函数,使用的非常多
现在有likes,address能否把likes和address里面的值挨个拿出来?
比如说:

select likes[0],likes[1],likes[2] from psn;

结果:
在这里插入图片描述
现在要实现这样的形式,把每个值都单独拿出来可以拿么?

select explode(likes) from psn;

在这里插入图片描述把里面的每个值都拿出来了,UDTF函数,非常好理解,输入是一个值,输出是N多个值

虽然hive里面支持了很多内置函数,但是这些内置函数,依然不够使用。举个例子:要对一个字符串进行脱敏操作,注册一个网站的时候,要给手机号发送验证码,158****7197,现在学的内置函数能完成操作么?
能,但是写起来会非常麻烦,所有这时候还需要UDF函数(用户自定义函数)

函数的分类:

UDF:用户自定义函数,输入一个值,输出也是一个值

select lpad(name,10,'*') from psn;

在这里插入图片描述
输入9条数据,输出的也是9条数据,是1:1的关系

UDAF:聚合函数,多进一出

count(),sum(),min(),max()都是聚合函数

UDTF:一进多出

官网拉到最后,创建用户自己的自定义函数。
在这里插入图片描述
HivePlugins
官方给了最直接的案例
Creating Custom UDFs

First, you need to create a new class that extends UDF, with one or more methods named evaluate.

package com.example.hive.udf;

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

public final class Lower extends UDF {
    
    
  public Text evaluate(final Text s) {
    
    
    if (s == null) {
    
     return null; }
    return new Text(s.toString().toLowerCase());
  }
}

首先定义一个类叫做Lower,集成UDF类
在类里面必须要实现一个方法,叫做evaluate()
有一个输入值,有一个输出值,返回之后就完事了。
这里也可以完成对应的基本操作

写完之后要把当前项目打成一个jar包。往集群里进行上传操作就可以了。
Deploying Jars for User Defined Functions and User Defined SerDes

In order to start using your UDF, you first need to add the code to the classpath:

hive> add jar my_jar.jar;

Added my_jar.jar to class path
这个时候意味着jar包已经加载成功了。这一步只是把代码加载到当前hive的classpath下面,还需要创建一个自定义函数。

create function my_db.my_lower as 'com.example.hive.udf.Lower';

创建完成,此时可以用了:

hive> select my_lower(title), sum(freq) from titles group by my_lower(title);

意味着刚才自定义的Java类实现了
但是要强调一个问题,把当前hive退出,Ctrl+C,再重新进来hive
进来之后再重新执行语句,FAILED: SemanticException [Error 10011]: Invalid function my_lower
意味着刚才的函数只是一个临时函数,这种操作不符合预期,可以执行第二种方式:
刚才是把jar包上传到本地Linux里面,直接add jar就加进去了,还可以:

hdfs dfs -mkdir /jar
hdfs dfs -put my_jar.jar /jar

成功之后可以创建另外一个函数:

create function tm2 as 'com.example.hive.udf.Lower' using jar 'hdfs://mycluster/jar/my_jar.jar'

此时也创建成功了,关闭会话再执行,因为现在把jar包上传到hdfs了,并且定义的时候指定了某一个hdfs路径,所以当开启会话的时候,方法确实失效了,但是方法定义的元数据并没有失效。下次再进来的时候,会从hdfs里面加载数据文件,成功之后再执行。推荐的方式。
把jar包上传到hdfs,而不要放在本地。
这个元数据存在MySQL哪里呢?

mysql -uroot -pok
use hive_remote
show tables;

找到FUNCS的表

select * from FUNCS;

有元数据会看到对应的存储。
在启动的时候,hive的内置函数确实是启动了,但是如果是自己额外加载的函数并没有进行启动过程。必须要重新把jar包加载进来,因为每次开启命令行之后,都是一个新的会话,初始化的新状态。
在写的时候注意,UDF类是必须要集成了,方法名称必须叫做evaluate,如果换一个名字是无效的

现在hive可以代替MapReduce做基本操作了,思考一个问题,是不是所有的MR任务都可以转成hive的sql语句来进行操作?
比如之前在写MapReduce的时候,最最基础的是Wordcount,能转成对应的sql语句来进行实现么?可以的,怎么来实现

vi wc
hadoop hve hi hello
hadoop hi
hive
hi helo hadoop
spark

把文件上传到hdfs里面

hdfs dfs -mkdir /wc
hdfs dfs -put wc /wc

第一件事:先创建对应的数据表

hive> create external table wc(line string) location '/wc';
hive> select * from wc;
hive> select split(line,' ') from wc;
select explode(split(line,' ')) from wc;

这样就把值拆开来了
在这里插入图片描述
拆完之后可以进行统计了,放统计结果怎么放?
先要创建一张结果表:

create table wc_result(word string,ct int);

从一张表里查询结果导入到另外一张表里,要用到嵌套子查询了。

from (select explode(split(line,' ')) word from wc) t insert into wc_result select word,count(word) group by t.word;

这就是最基本的写法,到公司之后如果见到100~200行的sql是很正常的事情,不要觉得奇怪,在大数据里面的表关联更加多
在这里插入图片描述在公司要根据情况来判断使用什么样的方式,sql还是MR
注意:
在这里插入图片描述

在这个任务中一共花费了40s,其中Map阶段16秒,reduce阶段9秒
剩下的15秒哪去了?在申请对应的资源
所有在写sql语句的时候看一下,如果MR执行的非常慢的话,有可能是在申请资源的时候浪费了很多时间,而不单单是MapReduce花费的时间,可以看一下时间做基本的对比。

hive在解析sql的时候使用了ANTLR词法语法分析工具

在这里插入图片描述
ANTLR,如果用hibernate,可以翻一下jar包,一定有一个ANTLR的jar包,同时可以看一下hive里面
在这里插入图片描述对应的语法解析的包,由这个包来完成由sql到对应的MR任务的解析过程。但注意了,还有另外一个东西,Apache也有一个SQL的解析工具,Calcite,一般也用来做语法解析用的也非常多。

猜你喜欢

转载自blog.csdn.net/m0_48758256/article/details/108776740
今日推荐