一 Hive简介

1.1. Hive的简介

1.1.1 什么是hive

hive是一个构建在Hadoop上的数据仓库工具(框架),可以将结构化的数据文件映射成一张数据表,并可以使用类sql的方式来对这样的数据文件进行读,写以及管理(包括元数据)。这套HIVE SQL 简称HQL。hive的执行引擎可以是MR、spark、tez。

如果执行引擎是MapReduce的话,hive会将Hql翻译成MR进行数据的计算。 用户可以使用命令行工具或JDBC驱动程序来连接到hive。

1.1.2 为什么使用hive

因为直接使用MapReduce,需要面临以下问题:

- 人员学习成本高
- 项目周期要求太短
- MapReduce实现复杂查询逻辑开发难度大

1.1.3 hive的优缺点

1) hive的优点

1.学习成本低
	提供了类SQL查询语言HQL(简单,容易上手),避免了直接写MapReduce(适合java语言不好的,sql熟练的人),减少开发人员的学习成本。
2.可扩展性好
	为超大数据集设计了计算/扩展能力(MR作为计算引擎,HDFS作为存储系统),Hive可以自由的扩展集群的规模,一般情况下不需要重启服务。
3.适合做离线分析处理(OLAP)
	Hive的执行延迟比较高,因此Hive常用于数据分析,对实时性要求不高的场合。
4.延展性好
	Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
5.良好的容错性
	某个数据节点出现问题HQL仍可完成执行。
6.统计管理
	提供了统一的元数据管理

2) hive的缺点

1. hive的HQL表达能力有限
  - 迭代式算法无法表达,比如PageRank(网页排名)
  - 数据挖掘方面,比如kmeans(k均值聚类算法)
2. hive的效率比较低
  - hive自动生成的mapreduce作业,通常情况下不够智能化
  - hive调优比较困难,粒度较粗

1.2. Hive架构和原理

1.2.1 hive的架构简介

hive 技巧 hive._hadoop

从上图可以看出,Hive的体系结构分为以下几部分:

1. 用户连接接口
	CLI:是指Shell命令行
	JDBC/ODBC:是指Hive的java实现,与传统数据库JDBC类似。
	WebUI:是指可通过浏览器访问Hive。
2. thriftserver:
	hive的可选组件,此组件是一个软件框架服务,允许客户端使用包括Java、C++、Ruby和其他很多种语言,通过编程的方式远程访问Hive。
3. 元数据
	Hive将元数据存储在数据库中,如mysql、derby。Hive中的元数据包括(表名、表所属的数据库名、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等)
4. 驱动器(Driver)
  - 解析器(SQLParser):
		将HQL字符串转换成抽象语法树AST,这一步一般都用第三方工具库完成,比如antlr;对AST进行语法
		分析,比如表是否存在、字段是否存在、SQL语义是否有误。	
	- 编译器(Compiler):
		对hql语句进行词法、语法、语义的编译(需要跟元数据关联),编译完成后会生成一个执行计划。hive上就
		是编译成mapreduce的job。
	- 优化器(Optimizer):
		将执行计划进行优化,减少不必要的列、使用分区、使用索引等。优化job。
	- 执行器(Executer):
		将优化后的执行计划提交给hadoop的yarn上执行。提交job。
5. hadoop
	Jobtracker是hadoop1.x中的组件,它的功能相当于:Resourcemanager+AppMaster
	TaskTracker相当于:Nodemanager  +  yarnchild
 
	Hive的数据存储在HDFS中,大部分的查询、计算由MapReduce完成

注意:

- 包含*的全表查询,比如select * from table 不会生成MapRedcue任务
- 包含*的limit查询,比如select * from table limit 3 不会生成MapRedcue任务

1.2.2 hive的工作原理

hive 技巧 hive._hive_02

1. 用户提交查询等任务给Driver。
2. 驱动程序将Hql发送编译器,检查语法和生成查询计划。
3. 编译器Compiler根据用户任务去MetaStore中获取需要的Hive的元数据信息。
4. 编译器Compiler得到元数据信息,对任务进行编译,先将HiveQL转换为抽象语法树,然后将抽象语法树转换成查询块,将查询块转化为逻辑的查询计划,重写逻辑查询计划,将逻辑计划转化为物理的计划(MapReduce), 最后选择最佳的策略。
5. 将最终的计划提交给Driver。到此为止,查询解析和编译完成。
6. Driver将计划Plan转交给ExecutionEngine去执行。
7. 在内部,执行作业的过程是一个MapReduce工作。执行引擎发送作业给JobTracker,在名称节点并把它分配作业到TaskTracker,这是在数据节点。在这里,查询执行MapReduce工作。
7.1 与此同时,在执行时,执行引擎可以通过Metastore执行元数据操作。
8. 执行引擎接收来自数据节点的结果。
9. 执行引擎发送这些结果值给驱动程序。
10. 驱动程序将结果发送给Hive接口。

1.2.3 hive和hadoop的关系

- hive本身其实没有多少功能,hive就相当于在hadoop上面包了一个壳子,就是对hadoop进行了一次封装。
- hive的存储是基于hdfs/hbase的,hive的计算是基于mapreduce。
参考下图:

hive 技巧 hive._Hive_03

1.3 hive与传统型数据库的区别

1. Hive采用了类SQL的查询语言HQL,因此很容易将Hive理解为数据库。其实从结构上来看,Hive和数据库除了拥有类似的查询语言,再无类似之处。

2. 数据库可以用在OLTP的应用中,但是Hive是为数据仓库而设计的,清楚这一点,有助于从应用角度理解Hive的特性。

3. Hive不适合用于联机事务处理(OLTP),也不提供实时查询功能。它最适合应用在基于大量不可变数据的批处理作业。Hive 的特点是可伸缩(在Hadoop 的集群上动态的添加设备),可扩展、容错、输入格式的松散耦合。Hive 的入口是DRIVER ,执行的SQL语句首先提交到DRIVER驱动,然后调COMPILER解释驱动,最终解释成MapReduce 任务执行,最后将结果返回。

4. MapReduce 开发人员可以把自己写的 Mapper 和 Reducer 作为插件支持 Hive 做更复杂的数据分析。 它与关系型数据库的 SQL 略有不同,但支持了绝大多数的语句(如 DDL、DML)以及常见的聚合函数、连接查询、条件查询等操作。

Hive和数据库的比较如下表:

比较项

关系数据库

Hive

ANSI SQL

支持

不完全支持

更新

UPDATE INSERT DELETE

INSERT OVERWRITE\ INTO TABLE

事务

支持

支持(部分支持)

模式

写模式

读模式

存储位置

块设备、本地文件系统

HDFS

延时



多表插入

不支持

支持

子查询

完全支持

只能用在From子句中

视图

Updatable

Read-only

可扩展性



数据规模

实时响应

毫秒级

秒级

详情解析

1、**查询语言**:由于SQL被广泛的应用在数据仓库中,因此,专门针对Hive的特性设计了类SQL的查询语言HQL。熟悉SQL开发的开发者可以很方便的使用Hive进行开发。

2、**数据存储位置**:Hive是建立在Hadoop之上的,所有Hive的数据都是存储在HDFS中的。而数据库则可以将数据保存在块设备或者本地文件系统中。

3、**数据格式**:Hive中没有定义专门的数据格式,数据格式可以由用户指定,用户定义数据格式需要指定三个属性:列分隔符(通常为空格、"\t"、"\x001")、行分隔符("\n")以及读取文件数据的方法(Hive中默认有三个文件格式TextFile、SequenceFile以及RCFile)。由于在加载数据的过程中,不需要从用户数据格式到Hive定义的数据格式的转换,因此,Hive在加载的过程中不会对数据本身进行任何修改,而只是将数据内容复制或者移动到相应的HDFS目录中。而在数据库中,不同的数据库有不同的存储引擎,定义了自己的数据格式。所有数据都会按照一定的组织存储,因此,数据库加载数据的过程会比较耗时。

4、**数据更新**:由于Hive是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive中不支持对数据的改写和添加,所有的数据都是在加载的时候中确定好的。而数据库中的数据通常是需要经常进行修改的,因此可以使用INSERT INTO...VALUES添加数据,使用UPDATE...SET修改数据。

5、**索引**:,Hive在加载数据的过程中不会对数据进行任何处理,甚至不会对数据进行扫描,因此也没有对数据中的某些Key建立索引。Hive要访问数据中满足条件的特定值时,需要暴力扫描整个数据,因此访问延迟较高。由于MapReduce的引入,Hive可以并行访问数据,因此即使没有索引,对于大数据量的访问,Hive仍然可以体现出优势。数据库中,通常会针对一个或几个列建立索引,因此对于少量的特定条件的数据的访问,数据库可以有很高的效率,较低的延迟。由于数据的访问延迟较高,决定了Hive不适合在线数据查询。

6、**执行**:Hive中大多数查询的执行是通过Hadoop提供的MapReduce来实现的(类似select * from tbl的查询不需要MapReduce)。而数据库通常有自己的执行引擎。

7、**执行延迟**:之前提到,Hive在查询数据的时候,由于没有索引,需要扫描整个表,因此延迟较高。另外一个导致Hive执行延迟高的因素是MapReduce框架。由于MapReduce本身具有较高的延迟,因此在利用MapReduce执行Hive查询时,也会有较高的延迟。相对的,数据库的执行延迟较低。当然,这个低是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。

8、**可扩展性**:由于Hive是建立在Hadoop之上的,因此Hive的可扩展性是和Hadoop的可扩展性是一致的。而数据库由于ACID语义的严格限制,扩展性非常有限。目前最先进的并行数据库Oracle在理论上的扩展能力也只有100台左右。

9、**数据规模**:由于Hive建立在集群上并可以利用MapReduce进行并行计算,因此可以支持很大规模的数据;对应的,数据库可以支持的数据规模较小。

Hive和Mysql的比较

- mysql用自己的存储存储引擎,hive使用的hdfs来存储。
- mysql使用自己的执行引擎,而hive使用的是mapreduce来执行。
- mysql使用环境几乎没有限制,hive是基于hadoop的。
- mysql的低延迟,hive是高延迟。
- mysql的handle的数据量较小,而hive的能handle数据量较大。
- mysql的可扩展性较低,而hive的扩展性较高。
- mysql的数据存储格式要求严格,而hive对数据格式不做严格要求。
- mysql可以允许局部数据插入、更新、删除等,而hive不支持局部数据的操作。

二 Hive的安装部署

Hive常用的安装分三种(注意:Hive会自动监测Hadoop的环境变量,如有就必须启动Hadoop)

先从本地上传Hive安装文件apache-hive-2.1.1-bin.tar.gz/root/soft

2.1 内嵌模式:

使用hive自带默认元数据库derby来进行存储,通常用于测试

  1. 优点:使用简单,不用进行配置
  2. 缺点:只支持单session。

2.1.1 安装步骤:

1)解压hive并配置环境变量

[root@zrclass01 local]# tar -zxvf apache-hive-2.1.1-bin.tar.gz -C /usr/local
#修改hive安装路径名,方便以后使用
[root@zrclass01 local]# mv apache-hive-2.1.1-bin/ hive


[root@zrclass01 local]# vi /etc/profile
# 添加如下内容:
export HIVE_HOME=/usr/local/hive
export PATH=$HIVE_HOME/bin:$PATH

#让profile生效
[root@zrclass01 local]# source /etc/profile

2) 配置hive-env.sh

如果不存在,就用hive.env.sh.template复制一个

export HIVE_CONF_DIR=/usr/local/hive/conf
export JAVA_HOME=/usr/local/jdk
export HADOOP_HOME=/usr/local/hadoop
export HIVE_AUX_JARS_PATH=/usr/local/hive/lib

3) 配置hive-site.xml

hive2.1.1中默认是没有hive-site.xml,可以把conf/hive-default.xml.template拷贝过来使用

[root@zrclass01 conf]# cp hive-default.xml.template hive-site.xml
[root@zrclass01 conf]# vi hive-site.xml

把hive-site.xml 中所有包含 ${system:java.io.tmpdir}替换成/usr/local/hive/iotmp.

如果系统默认没有指定系统用户名,那么要把配置${system:user.name}替换成当前用户名root

扩展:hive-site.xml中有两个重要的配置说明

<!-- 解决启动报错问题,去掉文件中所有带system: ,如${system:java.io.tmpdir}改为${java.io.tmpdir}  --> 
<property>
    <name>hive.exec.local.scratchdir</name>
    <value>${java.io.tmpdir}/${system:user.name}</value>
    <description>Local scratch space for Hive jobs</description>
  </property>
<!-- 该参数主要指定Hive的数据存储目录  -->
<property>
    <name>hive.metastore.warehouse.dir</name>
    <value>/user/hive/warehouse</value>
    <description>location of default database for the warehouse</description>
  </property>

<!-- 该参数主要指定Hive的临时文件存储目录  -->
 <property>
    <name>hive.exec.scratchdir</name>
    <value>/tmp/hive</value>
    <description>HDFS root scratch dir for Hive jobs which gets created with write all (733) permission. For each connecting user, an HDFS scratch dir: ${hive.exec.scratchdir}/<username">> is created, with ${hive.scratch.dir.permission}.</description>
  </property>

在linux中新建上面两个目录,并且进行权限赋值(可选操作,hive会自动创建)

[root@zrclass01 hive] # hdfs dfs -mkdir -p /user/hive/warehouse 
[root@zrclass01 hive] # hdfs dfs -mkdir -p /tmp/hive/ 
[root@zrclass01 hive] # hdfs dfs -chmod 750 /user/hive/warehouse 
[root@zrclass01 hive] # hdfs dfs -chmod 777 /tmp/hive
  1. 启动hadoop
[root@zrclass01 hadoop]# start-dfs.sh
[root@zrclass01 hadoop]# start-yarn.sh
  1. 初始化hive
[root@zrclass01 hive]# schematool --initSchema -dbType derby
  1. 启动hive

(注:启动之前要启动hdfs sbin/start-dfs.sh 和yarn sbin/start-yarn.sh )

[root@zrclass01 hive]# bin/hive

#进入后可以执行下面命令进行操作:
hive>show dataases;  #查看数据库
hive>show tables;   #查看表

简单sql演示执行

# 创建表
hive> create table dog(id int,name string);
hive> select * from dog;
hive> insert into dog values(1,"wangcai");
hive> desc dog; #查看表结构
hive> quit # 退出

2.2 本地模式

使用mysql替换derby进行元数据的存储,hive的相关进程都是在同一台机器上,即本地模式。mysql因为是独立的进程,所以mysql可以和hive在同一机器上,也可以在其他机器上。

hive 技巧 hive._hadoop_04

说明:

通常使用关系型数据库来进行元数据存储(mysql、oracle等执行带jdbc驱动的数据库)

  • 优点:支持多session
  • 缺点:需要配置、还需要安装mysql等关系型数据库

2.2.1 配置安装mysql

安装MySql服务器

mysql安装的步骤介绍

# 环境准备
# CentOS7中,系统默认采用的数据库是mariadb,这个数据库与MySQL冲突!
# 因此,在安装MySQL之前,需要先将其卸载!
[root@zrclass03 ~]# rpm -qa | grep mariadb			# 查询是否已经安装了mariadb
mariadb-libs-5.5.64-1.el7.x86_64								# 查询结果。如果没有这个结果,说明没有安装。

# 强制卸载mariadb
# --nodeps: 强制卸载,RPM卸载程序的时候,如果这个程序被其他的程序依赖,是无法卸载的。
#           此时,就需要使用--nodeps,忽略依赖,强制卸载。
# 下面的卸载命令中,卸载的包是上方查询到的包
[root@zrclass03 ~]# rpm -e mariadb-libs-5.5.64-1.el7.x86_64 --nodeps

# 安装MySQL
# 安装MySQL, 其实就需要安装 mysql-community-server, 但是它依赖其他的包
[root@zrclass03 mysql]# rpm -ivh mysql-community-common-5.7.28-1.el7.x86_64.rpm
[root@zrclass03 mysql]# rpm -ivh mysql-community-libs-5.7.28-1.el7.x86_64.rpm
[root@zrclass03 mysql]# rpm -ivh mysql-community-client-5.7.28-1.el7.x86_64.rpm
[root@zrclass03 mysql]# yum install -y net-tools
[root@zrclass03 mysql]# yum -y install perl
[root@zrclass03 mysql]# rpm -ivh mysql-community-server-5.7.28-1.el7.x86_64.rpm

# 开启MySQL服务
# 查看MySQL服务的运行状态
[root@zrclass03 ~]# systemctl status mysqld
# 如果MySQL服务没有开启,则开启
[root@zrclass03 ~]# systemctl start mysqld

# 登录到MySQL
# 在第一次开启MySQL服务的时候,会自动生成一个随机的密码
[root@zrclass03 ~]# grep password /var/log/mysqld.log			# 到mysqld.log文件中查找password
2020-12-16T07:47:14.117739Z 1 [Note] A temporary password is generated for root@localhost: pVLJs6&o(QQe
# 使用这个随机密码登录到MySQL
[root@zrclass01 ~]# mysql -u root -p
pHLSs6&o]GEe		# 这里用自己的密码登录

# 修改MySQL安全等级
# 1. 修改MySQL的密码策略(安全等级)
#    MySQL默认的密码安全等级有点高,在设置密码的时候,必须同时包含大小写字母、数字、特殊字符,以及对位数有要求
#show variables like '%validate_password%';					# 查看密码策略
set global validate_password_policy=LOW;						# 修改密码策略等级为LOW
set global validate_password_length=4;							# 密码的最小长度
set global validate_password_mixed_case_count=0;	  # 设置密码中至少要包含0个大写字母和小写字母
set global validate_password_number_count=0;			 	# 设置密码中至少要包含0个数字
set global validate_password_special_char_count=0;	# 设置密码中至少要包含0个特殊字符

# 2. 修改密码
alter user root@localhost identified by 'root';

# 3. 远程授权
grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;

2.2.2 配置hive的环境

1、解压并配置环境变量

2、配置hive的配置文件
cp hive-env.sh.template hive-env.sh
vi hive-env.sh(可以配置jdk、hive的conf路径)

3、在Hive的conf配置hive的自定义配置文件
vi hive-site.xml:添加如下内容

**注意:**前三步和内嵌模式一样

4、找到下面四个属性进行修改对应的值。

<!--配置mysql的连接字符串-->
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://zrclass03:3306/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<!--配置mysql的连接驱动-->
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<!--配置登录mysql的用户-->
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>
<!--配置登录mysql的密码-->
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>root</value>
<description>password to use against metastore database</description>
</property>

注意:hive的元数据在mysql库里创建的数据库hive的编码最好设置成latin1.

show variables like 'character%';

5、将mysql的驱动包mysql-connector-java-5.1.28-bin.jar上传到$HIVE_HOME/lib下(注意:驱动是jar结尾,不是tar结尾)

6、执行执行先要初始化数据库

[root@zrclass01 hive]# bin/schematool -initSchema -dbType mysql

7、启动hive

[root@zrclass01 hive]# bin/hive

说明:

2.3 远程模式

2.3.1 简介

将hive中的相关进程比如hiveserver2或者metastore这样的进程单独开启,使用客户端工具或者命令行进行远程连接这样的服务,即远程模式。客户端可以在任何机器上,只要连接到这个server,就可以进行操作。客户端可以不需要密码。

hive 技巧 hive._Hive_05

2.3.2 服务端的配置

1) 修改 hive-site.xml

<!--hive仓库在hdfs的位置-->
<property>
    <name>hive.metastore.warehouse.dir</name>
    <value>/user/hive/warehouse</value>
    <description>location of default database for the warehouse</description>
</property>

<!-- 该参数主要指定Hive的临时文件存储目录  -->
<property>
    <name>hive.exec.scratchdir</name>
    <value>/tmp/hive</value>
</property>

<!--连接mysql的url地址-->
<property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://zrclass03:3306/hive?createDatabaseIfNotExist=true&characterEncoding=latin1</value>
</property>
<!--mysql的驱动类-->
<property>
    <name>javax.jdo.option.ConnectionDriverName</name>
    <value>com.mysql.jdbc.Driver</value>
</property>
<!--mysql的用户名-->
<property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>root</value>
</property>
<!--mysql的密码-->
<property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>123456</value>
</property>


<!--hive工作的本地临时存储空间-->
<property>
    <name>hive.exec.local.scratchdir</name>
    <value>/usr/local/hive/iotmp/root</value>
</property>
<!--如果启用了日志功能,则存储操作日志的顶级目录-->
<property>
    <name>hive.server2.logging.operation.log.location</name>
    <value>/usr/local/hive/iotmp/root/operation_logs</value>
</property>
<!--Hive运行时结构化日志文件的位置-->
<property>
    <name>hive.querylog.location</name>
    <value>/usr/local/hive/iotmp/root</value>
</property>
<!--用于在远程文件系统中添加资源的临时本地目录-->
<property>
    <name>hive.downloaded.resources.dir</name>
    <value>/usr/local/hive/iotmp/${hive.session.id}_resources</value>
</property>

说明:使用远程模式,需要在hadoop的core-site.xml文件中添加一下属性

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

2.3.3 hive的两种服务说明

第一种服务:hiveserver2

1. 该服务端口号默认是10000
2. 可以单独启动此服务进程,供远程客户端连接;此服务内置metastore服务。
3. 启动方式:

    方法1:
        直接调用hiveserver2。会进入监听状态不退出。
    方法2:
        hive --service hiveserver2 & 进入后台启动
    方法3:
        hive --service hiveserver2 >/dev/null 2>&1 &; #信息送入黑洞。

第二种服务:metastore

1. 此服务才是真正连接元数据库的服务进程
2. 也可以让远程客户端连接
3. 启动方式:
	方法1:
		- hive --service metastore &
	方法2:
    - hive --service metastore 2>&1 >/dev/null &; #信息送入黑洞。

2.3.4 客户端连接hiveserver2服务

说明:

-1. 连接此服务的hive客户端,只需要配好环境变量即可
-2. 只能使用hive中的beeline连接工具进行连接此服务,beeline是hive的一个轻量级的连接客户端工具。

连接方式:

方式1:
   	step1. beeline 回车
   	step2. !connect jdbc:hive2://ip:10000 回车
   	step3. 输入用户名 回车
   	step4. 输入密码 回车
方法2(直连):
	1. beeline -u jdbc:hive2://ip:10000 -n 用户名

解析: 
	hive2,是hive的协议名称
	ip:  hiveserver2服务所在的主机IP。
	10000,是hiveserver2的端口号d

2.3.5 客户端连接metastore服务

注意:想要连接metastore服务的客户端必须配置如下属性和属性值

<property>
	<name>hive.metastore.uris</name> 
	<value>thrift://ip:9083</value>
</property>

解析:thrift:是协议名称
	 ip为metastore服务所在的主机ip地址
     9083是默认端口号