Hive学习笔记-入门(2)-Hive概述以及集群搭建

Hive概述

Hive是一款建立在Hadoop之上的开源数据仓库系统,可以将存储在HDFS中的结构化半结构化的数据文件映射为一张数据库表。之后基于表提供了一种类SQL的查询模型,称为Hive查询语言(HQL),用于访问和分析存储在HDFS中的大型数据集

Hive的核心是将HQL转换成MapReduce程序(后续也提供了其他的计算引擎),然后将程序提交的Hadoop集群中执行

使用Hive的好处:

  1. 直接使用MapReduce编程,学习成本较高。利用MapReduce实现复杂查询逻辑开发难度较大
  2. 使用Hive提供的HQL语法,学习成本较低,更加简单,容易上手
  3. 支持自定义函数,功能扩展很方便
  4. 依赖于Hadoop,擅长于存储分析海量数据集

从功能上来说,数据仓库软件至少需要具备存储数据分析数据的能力,Hive作为一款大数据时代的数据仓库软件,当然也具备这两种能力,但是这并不是它自己实现的,而是借助于Hadoop来实现的。Hive利用HDFS来存储数据,利用MapReduce来查询和分析数据。而Hive本身最大的意义在于能够让用户专注于编写HQL,然后让Hive将其转换成MapReduce程序,完成对数据的分析

Hive架构和组件

架构

考虑Hive完成的功能,它能够将HDFS上的数据文件映射成为一张表,并在其上提供HQL的查询功能。

  • 数据文件到表的映射,需要记录文件和表之间的对应关系,这类数据我们称之为元数据信息(描述数据的数据)。具体来说,元信息中可能需要记录表的位置信息、字段的顺序信息、字段之间的分隔符等
  • HQL的查询功能,需要提供SQL的语法解析和编译功能。用户写完SQL之后,Hive需要对语句进行语法校验,并根据记录的元数据信息来解读语句的含义,指定执行计划,并将执行计划转换成MapReduce程序来执行,然后将执行结果封装返回给用户

总体来说,Hive架构如下:

用户编写查询语句之后,Hive对其进行语法解析,语句编译和执行计划优化。在语句编译的过程中,需要使用到元数据,因此需要从存储元数据的数据库中查询对应的信息。之后Hive将语句转换成MapReduce程序后提交给Yarn进行执行,得到结果后返回给用户。

组件

Hive的组件主要包括如下的内容,如用户接口、元数据存储、Driver驱动程序、执行引擎等,图中还包括与集群的交互等信息

  • 用户接口:包括命令行接口CLI、JDBC/ODBC、WebGUI等。其中,Hive中的Thrift服务器允许外部客户端通过网络与Hive进行交互,类似于JDBC或者ODBC协议;WebGUI则是通过浏览器来访问Hive

  • 元数据存储:Hive的元数据通常是存储在关系数据库如MySQL或者derby中。Hive中的元数据包括表的名字、表的列和分区及其属性、表的属性、表数据所在目录等

  • Driver驱动程序:包括语法解析器、计划编译器、优化器、执行器等,主要完成HQL查询语句的词法分析、语法分析、编译、优化,以及查询计划的生成,生成的查询计划存储在HDFS中,并有执行引擎调用执行

  • 执行引擎:Hive本身并不处理数据文件,而是通过执行引擎来处理。当前Hive支持MapReduce、Tez、Spark三种执行引擎

Tez:是Apache最新的支持DAG作业的开源计算框架,它可以将多个有依赖的作业转换为一个作业从而大幅提升DAG作业的性能。

Hive数据模型

Hive中的数据模型类似于关系型数据库的库表结构,在此基础上还有自己特有的模型,Hive中的数据可以在粒度级别上分成三类:Table表、Partition分区和Bucket分桶。

Database数据库

  • Hive作为一个数据仓库,其中也有数据库的概念。每个数据库下有属于自己的表。默认存在数据库为default
  • Hive中的数据都是存储在HDFS上的,存储目录和数据模型的对应也比较清晰。默认存在根目录,可以在hive-site.xml中定义参数hive.metastore.warehouse.dir来指定,默认值为/user/hive/warehouse
  • 每个数据库在根目录下占据一项,以数据库名称命名,存储路径为${hive.metastore.warehouse.dir}/databasename.db

Table表

  • Hive表于类似于关系数据库中的表。Hive中表所对应的数据通常存储在HDFS中,表相关的元数据存储在另外的RDBMS中
  • Hive中表数据在HDFS上的存储路径为:${hive.metastore.warehouse.dir}/databasename.db/tablename
  • 默认数据库中的表直接存放在根目录下

Partition分区

  • Partition分区是对Hive的一种优化手段,指的是根据分区列的值来将表划分为不同的分区(例如按照时间列对表进行划分),这样可以更快地对指定分区数据进行查询
  • 分区在存储层面上的表现是对应表目录下的子文件夹
  • 一个文件夹表示一个分区,子文件的命名标准为分区列=分区值
  • Hive支持分区下继续创建分区,即多重分区

Bucket分桶

  • Bucket分桶也是Hive的一种优化手段,指的是根据表中字段的值,经过hash计算规则之后将数据文件划分成若干个小文件
  • 分桶的好处是可以优化join查询和方便抽样查询
  • 分桶在存储层面的表示是同一个表目录下数据根据hash散列之后变成了多个文件

Hive虽然具有RDBMS数据库的外表,包括数据模型、SQL语法都十分相似,但应用场景却完全不同。Hive只适合用来做海量数据的离线分析。Hive的定位是数据仓库,面向分析的OLAP系统。Hive不是大型数据库,也不是要取代MySQL承担业务数据处理。

Hive部署

元数据和元数据服务

元数据:Metadata,又称为中介数据、中继数据,指的是描述数据的数据。它主要是用来描述数据的属性,用来支持相关功能,如指示存储位置、历史数据、资源查找、文件记录等

Hive Metadata即Hive中的元数据,其中包含了Hive创建的database、table、表位置、类型、属性、字段顺序、字段类型等元信息。Hive元数据存储在关系型数据库中,如Hive内置的Derby,或第三方数据库如MySQL等

Hive Metastore即元数据服务,它的作用是管理元数据,对外暴露服务地址,让各种客户端通过连接Metastore服务,再由Metastore去连接MySQL数据库来进行元数据的存取,相当于对元数据的操作有了一个统一的接口

有了Meatstore服务,就可以有多个客户端同时连接,这些客户端不需要知道MySQL数据库的用户名和密码,只需要连接Metastore服务即可,在某种程度上保证了Hive元数据的安全

Hive部署

Hive的部署有三种模式,内嵌模式、本地模式和远程模式。三种模式的区分主要在于两点:

  1. Metastore服务是否需要单独配置,单独启动
  2. Metadata是存储在Hive内置的Derby中,还是第三方的RDBMS如MySQL中
内嵌模式 本地模式 远程模式
Metastore单独配置、启动
Metadata存储介质 Derby MySQL MySQL

Hadoop和Hive之间的版本对应关系可以参考:Downloads (apache.org)

目前集群中使用的Hadoop版本为3.1.3,因此这里选择使用的Hive版本为3.1.2

Hive是一款基于Hadoop的数据仓库软件,因此在部署之前,需要保证服务器的基础环境正常,Hadoop集群健康可用。启动Hive之前必须先启动Hadoop集群,需要等待HDFS安全模式关闭之后再启动运行Hive。Hive不是分布式安装运行的软件,其分布式的特征主要是借由Hadoop完成,包括分布式存储、分布式计算等。

在部署之前,需要将Hadoop与Hive进行整合。我们需要在Hadoop中添加相关配置信息,满足Hive在Hadoop上运行,具体信息如下,配置在core-site.xml中,并同步到集群中的其他节点上。

1
2
3
4
5
6
7
8
9
<!--Hadoop与Hive的整合-->
<property>
<name>hadoop.proxyuser.syh.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.syh.groups</name>
<value>*</value>
</property>

该处参考:错误:hive中beeline连接异常User:*** is not allowed to impersonate - Jtotoo - 博客园 (cnblogs.com)

其中syh可以修改为自己对应的用户

内嵌模式

内嵌模式的特征就是不需要配置启动Metastore服务,解压安装包初始化即可测试体验Hive。

Hive3版本需要用户手动进行元数据初始化动作

具体配置过程如下:

将安装包上传到集群中,然后解压到/opt/module目录下,为了后续方便可以进行名称修改。

1
2
tar -zxvf apache-hive-3.1.2-bin.tar.gz -C /opt/module
mv apache-hive-3.1.2-bin/ hive-3.1.2

编辑环境变量/etc/profile.d/my_env.sh,在其中添加Hive对应的目录

1
2
3
#HIVE_HOME
export HIVE_HOME=/opt/module/hive-3.1.2
export PATH=$PATH:$HIVE_HOME/bin

之后需要解决hadoop、hive之间的guava版本差异

1
2
3
cd /opt/module/hive-3.1.2
rm -r lib/guava-19.0.jar
cp /opt/module/hadoop-3.1.3/share/hadoop/common/lib/guava-27.0-jre.jar ./lib/

然后修改hive环境变量文件hive-env.sh,在其中添加Hadoop的配置,具体位置在$HIVE_HOME/conf目录下,需要将后缀的.template删除,在里面添加如下内容:

1
2
3
export HADOOP_HOME=/opt/module/hadoop-3.1.3
export HIVE_CONF_DIR=/opt/module/hive-3.1.2/conf
export HIVE_AUX_JARS_PATH=/opt/module/hive-3.1.2/lib

配置完成之后,就可以初始化metadata了

1
2
cd /opt/module/hive-3.1.2
bin/schematool -dbType derby -initSchema

这样,Hive的安装就完成了,同时我们可以启动Hive服务,之后进入的就是类似于mysql中那样的命令行画面

1
bin/hive

(以上的操作是Hive的安装过程,在后续的不同部署方式中也是通用的)

在内嵌模式下,判断是否初始化成功的依据是执行命令之后输出信息和执行命令的当前路径下是否有文件产生。

在不同的目录启动hive,文件产生在不同的目录下,则隔离了不同用户的操作,不同用户之间的操作不是共享的,这也是内嵌模式不被使用在生产场景下的原因,只适合用来测试。

本地模式

本地模式的特征就是需要安装数据库MySQL来存储元数据,但是不需要配置Metastore服务,Metastore服务随着hive的启动而启动,也就是可能同时出现多个Metastore服务(同样Hive3版本需要用户手动进行元数据初始化操作)

具体部署过程如下:

首先需要安装MySQL,具体过程可以参考文章:CentOS7中安装MySQL - EverNorif

之后需要安装Hive,大致过程和上面内嵌模式类似,但是有一些不同。

需要将MySQL JDBC驱动移动到$HIVE_HOME/lib目录下

1
mysql-connector-java-5.1.32.jar

需要在hive的conf目录下新增hive-site.xml文件,其中配置mysql等相关信息。配置信息如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<configuration>
<!-- 存储元数据mysql相关配置 -->
<!-- JDBC连接的URL -->
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value> jdbc:mysql://hadoop102:3306/hive?createDatabaseIfNotExist=true&amp;useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8</value>
</property>
<!-- JDBC连接的Driver -->
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<!-- JDBC连接的username -->
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<!-- JDBC连接的密码 -->
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123123</value>
</property>

<!-- 关闭元数据存储授权 -->
<property>
<name>hive.metastore.event.db.notification.api.auth</name>
<value>false</value>
</property>

<!-- 关闭元数据存储版本的验证 -->
<property>
<name>hive.metastore.schema.verification</name>
<value>false</value>
</property>

<!-- Hive 默认在 HDFS 的工作目录 -->
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>

</configuration>

之后就可以初始化metadata,然后启动hive服务。

1
bin/schematool -initSchema -dbType mysql -verbos

远程模式

远程模式的特点是需要安装MySQL来存储Hive元数据,并且需要手动单独配置启动Metastore服务。

远程模式的安装也和上面的步骤类似,只有部分细节有所差异。

首先安装MySQL,然后安装Hive,同样需要上传MySQL JDBC驱动,以及新增hive-site.xml配置MySQL等相关信息,配置信息如下,和本地模式不同的是增加了HiveServer2绑定运行以及远程模式部署Metastore服务的地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<configuration>
<!-- 存储元数据mysql相关配置 -->
<!-- JDBC连接的URL -->
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value> jdbc:mysql://hadoop102:3306/hive?createDatabaseIfNotExist=true&amp;useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8</value>
</property>
<!-- JDBC连接的Driver -->
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<!-- JDBC连接的username -->
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<!-- JDBC连接的密码 -->
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123123</value>
</property>

<!-- 指定HiveServer2连接的host -->
<property>
<name>hive.server2.thrift.bind.host</name>
<value>hadoop102</value>
</property>

<!-- 指定 hiveserver2 连接的端口号 -->
<property>
<name>hive.server2.thrift.port</name>
<value>10000</value>
</property>

<!-- 远程模式部署metastore 服务地址 -->
<property>
<name>hive.metastore.uris</name>
<value>thrift://hadoop102:9083</value>
</property>

<!-- 关闭元数据存储授权 -->
<property>
<name>hive.metastore.event.db.notification.api.auth</name>
<value>false</value>
</property>

<!-- 关闭元数据存储版本的验证 -->
<property>
<name>hive.metastore.schema.verification</name>
<value>false</value>
</property>

<!-- Hive 默认在 HDFS 的工作目录 -->
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
</property>
</configuration>

之后就可以启动运行Hive了。在远程模式下,直接运行Hive服务会报错 ,必须首先启动Hive Metastore服务之后才可以使用Hive。(在使用前还需要初始化metadata)

1
bin/schematool -initSchema -dbType mysql -verbos

启动Hive Metastore服务:

1
2
3
4
5
6
7
8
9
10
11
cd $HIVE_HOME

# 前台启动,使用ctrl+c关闭
bin/hive --service metastore

# 前台启动开启debug日志
bin/hive --service metastore --hiveconf hive.root.logger=DEBUG,console

# 后台启动,进程挂起,关闭使用jps+kill
# 输入命令回车执行 再次回车 进程将挂起后台
nohup /export/server/hive/bin/hive --service metastore &

Hive客户端

客户端介绍

从Hive远程模式图解中我们可以看到,Hive有两种连接方式的,分别是旧客户端bin/hive以及新客户端bin/beeline

第一代客户端:$HIVE_HOME/bin/hive,目前已经不推荐使用了。它是一个shellUtil,主要功能是用于以交互式或批处理模式进行Hive查询,以及启动Hive相关的服务,例如metastore

第二代客户端:$HIVE_HOME/bin/beeline,是一个JDBC客户端,官方推荐使用。与第一代客户端相比,它的性能得到了加强,安全性也得到了提高

Beeline在嵌入式模式和远程模式下均可以工作。在嵌入模式下,它运行嵌入式Hive,而远程模式下通过Thrift连接到到单独的HiveServer2服务上

  • HiveServer和HiveServer2是Hive自带的两种服务,允许客户端在不启动命令行的情况下对Hive中的数据进行操作,同时允许远程客户端使用多种编程语言如Java,Python等向Hive提交请求,取回结果
  • HiveServer不能处理多余一个客户端的并发请求,因此在Hive-0.11.0版本中重写了代码得到HiveServer2解决该问题。目前HiveServer已经被废弃
  • HiveServer2支持多客户端的并发和身份认证,旨在为开放API客户端如JDBC,ODBC等提供更好的支持

第一代客户端hive的启动:直接通过hive命令启动即可。

  • 如果是远程模式部署,需要手动启动metastore服务;如果是内嵌模式和本地模式,则运行hive的时候,metastore服务会随之一起启动
  • 可以在启动Hive Metastore服务的机器上直接使用hive客户端
  • 也可以在其他机器上通过hive访问Hive Metastore服务,只需要在该机器的hive-site.xml中配置metastore服务地址即可

第二代客户端beeline的启动:需要首先启动metastore服务,然后启动hiveserver2服务

1
2
3
# 后台启动
nohup hive --service metastore &
nohup hive --service hiveserver2 &

之后就可以通过beeline客户端进行连接,协议的地址为jdbc:hive2://hadoop102:10000,需要登陆对应的用户

1
2
3
4
5
6
7
8
9
# 方式1
beeline

beeline> ! connect jdbc:hive2://hadoop102:10000
Connecting to jdbc:hive2://hadoop102:10000
Enter username for jdbc:hive2://hadoop102:10000: syh
Enter password for jdbc:hive2://hadoop102:10000: ******
Connected to: Apache Hive (version 3.1.2)
Driver: Hive JDBC (version 3.1.2)
1
2
# 方式2
beeline -u jdbc:hive2://hadoop102:10000 -n syh

可能出现的问题

在连接二代客户端的时候可能会出现以下的问题:

  • 拒绝连接
1
2
3
4
5
Could not open connection to the HS2 server.Please check the server URI and if
the URI is correct,then ask the administrator to check the server status.
Error:Could not open client transport with JDBC Uri:
idbc:hive2://hadoop102:10000:java.net.ConnectException:Connection refused
(Connection refused)(state=08S01,code=0)
  • 权限不够
1
Failed to open new session: java.lang.RuntimeException: org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.security.authorize.AuthorizationException): User: syh is not allowed to impersonate syh 

该问题的解决可以参考:Beeline连接报错:Could not open client transport with JDBC Uri: jdbc:hive2://localhost:10000/default_望隐少年的博客-CSDN博客

其中需要注意的点是HiveServer2服务的启动较慢,只有当我们看到10000端口占用之后,服务才启动完毕。需要等到服务启动完毕之后再连接beeline

我们也可以通过在hive-site.xml中进行相应的配置来提高HiveServer2服务的启动速度

1
2
3
4
5
6
<!-- hiveserver2的高可用参数,开启此参数可以提高hiveserver2的启动速度 -->

<property>
<name>hive.server2.active.passive.ha.enable</name>
<value>true</value>
</property>

启动脚本

可以编写Hive服务启动脚本myHiveService.sh,分别完成以下功能

  • 启动Metastore服务和HiveServer2服务
  • 查看Metastore服务和HiveServer服务状态
  • 停止Metastore服务和HiveServer2服务

脚本启动两个服务之后,需要手动查看服务状态,两个服务都正常启动之后才可以连接客户端

具体内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/bin/bash
HIVE_LOG_DIR=$HIVE_HOME/logs
if [ ! -d $HIVE_LOG_DIR ]; then
mkdir -p $HIVE_LOG_DIR
fi
#检查进程是否运行正常,参数 1 为进程名,参数 2 为进程端口
function check_process() {
pid=$(ps -ef 2>/dev/null | grep -v grep | grep -i $1 | awk '{print $2}')
ppid=$(netstat -nltp 2>/dev/null | grep $2 | awk '{print $7}' | cut -d '/' -f 1)
echo $pid
[[ "$pid" =~ "$ppid" ]] && [ "$ppid" ] && return 0 || return 1
}
function hive_start() {
metapid=$(check_process HiveMetastore 9083)
cmd="nohup hive --service metastore >$HIVE_LOG_DIR/metastore.log 2>&1 &"
[ -z "$metapid" ] && eval $cmd || echo "Metastroe 服务已启动"
server2pid=$(check_process HiveServer2 10000)
cmd="nohup hiveserver2 >$HIVE_LOG_DIR/hiveServer2.log 2>&1 &"
[ -z "$server2pid" ] && eval $cmd || echo "HiveServer2 服务已启动"
}
function hive_stop() {
metapid=$(check_process HiveMetastore 9083)
[ "$metapid" ] && kill $metapid || echo "Metastore 服务未启动"
server2pid=$(check_process HiveServer2 10000)
[ "$server2pid" ] && kill $server2pid || echo "HiveServer2 服务未启动"
}
case $1 in
"start")
hive_start
;;
"stop")
hive_stop
;;
"restart")
hive_stop
sleep 2
hive_start
;;
"status")
check_process HiveMetastore 9083 >/dev/null && echo "Metastore 服务运行正常" || echo "Metastore 服务运行异常"
check_process HiveServer2 10000 >/dev/null && echo "HiveServer2 服务运行正常" || echo "HiveServer2 服务运行异常"
;;
*)
echo Invalid Args!
echo 'Usage: '$(basename $0)' start|stop|restart|status'
;;
esac

Hive初体验

Hive VS MySQL

  • Hive SQL的语法和标准的SQL很类似,使得学习成本降低很多
  • Hive底层通过MapReduce执行数据插入动作,速度慢

Hive表映射

1
2
3
4
5
6
create table test(
id int,
name varchar(255),
age int,
city varchar(255)
) row format delimited fields terminated by ','
  • Hive应该具有自己特有的数据插入表的方式,即从HDFS文件映射成为表
  • 想在Hive中创建表,并与结构化文件映射成功,需要注意
    • 创建表时,字段顺序、字段类型需要和文件中保持一致。类型不一致hive会尝试转换,但是不保证成功。不成功显示null
    • 文件放置在Hive表对应目录下可以映射成功(但是可能不一定需要放在对应目录?)
    • 建表的时候需要指定内容分隔符(但是可能不一定需要指定?)

Hive学习笔记-入门(2)-Hive概述以及集群搭建
http://example.com/2022/07/02/Hive学习笔记-入门-2-Hive概述以及集群搭建/
作者
EverNorif
发布于
2022年7月2日
许可协议