第 1 章 Hive 概述

2022年4月24日 563点热度

今天我们从零开始学习大数据核心技术里面的一个非常重要的技术:Hive。它是我们大数据处理过程中使用比较广泛的技术。我们将从它的产生背景、优缺点、系统架构原理、与传统关系型数据库的比较以及运行模式等方面进行学习。

在开始学习 Hive 之前,我们已经学习过了 Hadoop 相关的知识。Hive 需要以 Hadoop 作为基础,因此,没系统学习过 Hadoop 的同学可以先去学习这方面的知识。

我们先回顾一下 Hadoop 里面的知识点 —— MapReduce 计算框架。

MapReduce 计算框架

我们都知道,Hadoop 中的 MapReduce 计算框架模型能将计算一个大任务切分成多个小任务,然后将小任务分布到多个计算节点上去执行,进而降低计算成本并提高扩展性。

但是,我们在使用 MapReduce 进行编程的过程中会觉得 MapReduce 数据处理的门槛比较高并且流程还比较繁杂。需要我们具备 Java 编程基础,才能熟练使用 MapReduce 进行编程。

那么有没有一种技术:即使我们对 MapReduce 编程不是很熟练也能进行大数据分析呢?

有,那就是我们今天要学的——Apache Hive。

1.1 什么是 Hive

1.1.1 Hive 的产生背景

Apache Hive 最初由 Facebook(脸书,现改名为:元宇宙)的数据工程师开发,后来2008年贡献给 Apache 软件基金会,现已成为 Apache 顶级项目。目前国内外有很多公司使用和开发 Apache Hive。

Apache Hive™ 是一个在 Hadoop 集群之上运行的开源数据仓库和分析包,使用 类SQL 语法读取 Hadoop HDFS 数据,分析保存在分布式存储中 HDFS 或者 HBase 数据库中的大型数据集。

它的核心功能就是:将结构化的数据文件映射为一张数据库表,并提供类 SQL查询功能,同时将 HQL 语句转化为 MapReduce 作业进行运行

因此,我们只需要掌握 SQL 相关知识就可以进行数据分析,并不一定要精通 MapReduce 编程。这给我们带来了极大的便利,同时降低了我们的学习成本。

1.1.2 Hive 的发展历史

接下来,我们来看一下 Apache Hive 各版本发布的时间节点,表中省略了小版本发布时间。通过下表我们知道 Hive 和 Hadoop 的版本对应关系。

发布时间 发行版本以及Hadoop支持
2007-2008 诞生于 Facebook
2013-01 发布Hive 0.10.0版本,支持Hadoop 0.20.x、0.23.x.y、1.x.y、2.x.y
2013-05 发布Hive 0.11.0版本,支持Hadoop 0.20.x、0.23.x.y、1.x.y、2.x.y
2013-10 发布 Hive 0.12.0版本,支持Hadoop 0.20.x、0.23.x.y、1.x.y、2.x.y
2014-04 发布 Hive 0.13.0版本,支持Hadoop 0.20.x、0.23.x.y、1.x.y、2.x.y
2014-11 发布 Hive 0.14.0版本,支持 Hadoop 1.x.y、2.x.y
2015-02 发布 Hive 1.0.0版本,支持 Hadoop 1.x.y、2.x.y
2016-02 发布 Hive 2.0.0版本,支持 Hadoop 2.x.y
2018-05 发布 Hive 3.0.0版本,支持 Hadoop 3.x.y
2018-07 发布 Hive 3.1.0版本,支持 Hadoop 3.x.y
2018-11 发布 Hive 3.1.1版本,支持 Hadoop 3.x.y
2018-11-07 发布 Hive 2.3.4版本,支持 Hadoop 2.x.y
2019-05-14 发布 Hive 2.3.5版本,支持 Hadoop 2.x.y
2019-08-26 发布 Hive 3.1.2 版本,支持 Hadoop 3.x.y
2020-04-18 发布 Hive 2.3.7版本,支持 Hadoop 2.x.y
2021-01-17 发布 Hive 2.3.8版本,支持 Hadoop 2.x.y
2021-06-09 发布 Hive 2.3.9版本,支持 Hadoop 2.x.y
2022-04-08 发布 Hive 3.1.3版本,支持 Hadoop 3.x.y

1.1.3 Hive 与 Hadoop

通过前面的知识我们已经知道,Hive 是需要以 Hadoop 为支撑的,因此我们有必要了解 Hive 和 Hadoop 之间的关系。

  1. Hive 是基于 Hadoop 的一个数据仓库工具;它是 MapReduce 的一个封装,底层就是 MapReduce 程序;
  2. Hive 将 HQL 语句转化为 MapReduce 程序。Hive 没有服务端,它本质就是 Hadoop 或者说是 HDFS 的一个客户端,对 HDFS 的数据和 Meta Store(元数据)进行操作;
  3. Hive 处理的数据实际存放在 HDFS 中,默认的路径是:/user/hive/warehouse;
  4. Hive 调度资源时,使用的是 YARN 框架;
  5. 在启动 Hive 之前,需要先启动 Hadoop 集群(这里面包含启动 HDFS 和 YARN)。

因此,通过以上几点我们对 Hive 和 Hadoop 之间的关系有了一定了解。

1.2 Hive 的优缺点

可能有同学说,我们都还没有用过 Hive ,怎么知道它的优缺点呢?其实不然,我们通过前面的知识可以总结出它的优缺点。

1.2.1 优点

  1. 简单。只需要编写类似 SQL 语句就行;
  2. 成本低。避免了去写 MapReduce,减少学习成本;
  3. Hive 的执行延迟比较高,因此 Hive 常用于数据分析,对实时性要求不高的场合;
  4. Hive 优势在于处理大数据,对于处理小数据没有优势,因为 Hive 的执行延迟比较高。
  5. 自定义函数。Hive 支持自定义函数,可以根据具体的需求来实现自定义函数。

我们知道不管什么技术都有利有弊,同样的,Hive 也有它不足的地方。

1.2.2 缺点

  1. Hive 自动生成 MapReduce 作业,通常不够智能化,效率比较低;
  2. 不擅长数据挖掘(擅长数据挖掘的是Spark);
  3. Hive 调优一般比较困难,粒度较粗;
  4. Hive 本身并不提供数据的存储功能,数据一般都是存储在 HDFS 上的(对数据完整性、格式要求并不严格);
  5. Hive 是专为 OLAP(在线分析处理) 设计,不支持事务。

我们可以看到,Hive 的缺点还是比较明显的。

1.3 Hive 的架构原理

1.3.1 Hive 的系统架构

下面我们来看看 Hive 的系统架构,这里说到【系统架构】,其实指的是 Hive 主要由哪几部分组件组成,每个组件主要功能是什么?组件之间如何协调工作?看下面的大图:

图1-1 Hive系统架构图

从上图我们可以看出 Hive 系统结构主要由四部分组成:

  1. 用户接口层(User Inferface)
  2. 跨语言服务层(Thrift Server)
  3. 底层的驱动引擎层(Driver)
  4. 元数据服务层(MetaStore)

用户接口层:

它主要有 3 个,分别是 CLI、JDBC/ODBC 和 WEB UI。

其中 CLI 指的是 Shell 终端命令行,这是最常用的一种方式。

JDBC/ODBC 是 Hive 的 Java 实现,与使用传统数据库 JDBC 的方式类似。

WEB UI 指的是通过浏览器的方式访问 Hive。

跨语言服务层:

Thrift 是 Facebook 公司开发的一个软件框架,主要用来进行可扩展且跨语言的服务。

Hive 已经集成了该服务,我们可以使用不同的编程语言(如Java、Python等)调用 Hive 的接口。

驱动引擎层:

这一层是整个 Hive 系统架构中最为重要的一层。

在这一层重主要包含了:

  1. 解析器(SQL Parser)
  2. 编译器(Compiler)
  3. 优化器(Optimizer)
  4. 执行器(Executer)

解析器的作用:将 SQL 字符串转换成抽象语法树 AST,这一步一般都用第三方工具库完成,比如 antlr;对 AST 进行语法分析,比如表是否存在、字段是否存在、SQL 语义是否有误;

编译器的作用:将 AST 编译生成逻辑执行计划;

优化器的作用:对逻辑执行计划进行优化;

执行器的作用:把逻辑执行计划转换成可以运行的物理计划。对于 Hive 来说,就是 MapReduce 或者 Spark。

元数据服务层:

Hive 中的元数据通常包含:表名、列、分区及其相关属性,表数据所在目录的位置信息,MetaStore 默认存在自带的 Derby 数据库中。

由于 Derby 数据库不适合多用户操作,并且数据存储目录不固定,不方便管理,因此,通常都是将元数据存储在 MySQL 数据库。

Hadoop 集群:

Hive 需要依赖 Hadoop,是因为 Hive 中的参与运算的真实数据存在 HDFS 中,使用 MapReduce 进行计算。Hadoop可以说是 Hive 的基石。

以上就是我们对 Hive 系统架构的直观认识。接下来我们看一下这些组件是如何协调运行的,也就是 Hive 的执行流程。

1.3.2 Hive 的运行机制

我们在进行学习的时候最好参考官方网站上的资料,因为比较权威。为了正确理解 Hive 的运行机制,我在 Hive 官网上找到如下架构图:

图1-2 Hive 官方架构图

上图的执行流程大致步骤是这样:

  1. 我们提交查询等任务给 Driver;
  2. Driver 为查询操作创建了一个 Session Handler,接着 Driver 发送查询操作到 Compiler(编译器)去生成一个 execute plan(执行计划);
  3. Compiler(编译器) 根据我们的查询任务去 MetaStore 中获取需要的 Hive 的元数据信息。这些元数据在后续的 stage 中用作抽象语法树的类型检测和修剪;
  4. Compiler(编译器)得到元数据信息,对 task 进行编译,先将 HQL 转换为抽象语法树,然后将抽象语法树转换为查询块,将查询块转化为逻辑的查询 plan,重写逻辑查询 plan,将逻辑 plan 转化为物理的 plan(MapReduce),最后选择最佳策略;
  5. 将最终的 plan 提交给 Driver;
  6. Driver 将 plan 转交给 Execution Engine 去执行,将获取到的元数据信息,提交到 JobTracker 或者 Resource Manager 执行该 task,查询任务会直接读取到 HDFS 中进行相应的操作;
  7. 获取执行的结果;
  8. 获取并返回执行结果。

但上图概括度比较过大,没有具体表现出每个组件的主要作用,我通过查询各种资料整理出了下面这套直观的流程图,请看:

图1-3 Hive 直观流程图

简化后的执行流程:

  1. 开始 HQL 被提交给客户端;
  2. 解析器对 HQL 进行语法解析生成 AST;
  3. 遍历 AST 生成 QeuryBlock;
  4. Logic Plan Generator 将 QB 转换成逻辑执行计划;
  5. Logic Optimizer 优化逻辑执行计划;
  6. Physical Plan Gernerator 将逻辑计划转化成物理计划;
  7. Physical Optimizer 将生成的物理计划进行优化;
  8. 最终将完整的计划交由引擎去执行。

所以,本质上 Hive 工作的过程就是将 HQL 语句解析成引擎执行的过程。

1.3.3 Hive 的数据模型

Hive 的运行机制随着我们深入地学习会越来越清晰,我们现在只需要在脑海中有大体的印象就可以了。

下面我们来看一下 Hive 的数据存储模型,也就是数据在 Hive 中具体的表现形式。

Hive 中的数据模型主要有 3 种:表(Table)、分区(Partitions)、桶(Buckets)。Hive 数据存储模型如下图所示:

图1-4 Hive 数据存储模型

数据库:相当于关系型数据库中的命名空间(NameSpace),它的作用是将用户和数据库的应用隔离到不同的数据库中或者模式中。

表:Hive 的表在逻辑上由存储的数据和元数据组成。存储的数据主要存放在分布式文件系统中,比较典型的就是 HDFS。在 Hive 中的表主要分类两类:内部表外部表

内部表:该表内的数据存储在 Hive 数据仓库中。

外部表:该表内的数据既可以存储在 Hive 数据仓库外的分布式文件系统中,也可以存储在 Hive 数据仓库中。

注意:Hive 数据仓库是 HDFS 中的一个目录,这个目录就是 Hive 数据存储的默认路径,可以在 Hive 配置文件中配置,最终也会存储到元数据中。

分区:通过对表概念的分析,我们可以知道表在 HDFS 中的表现形式就是一个目录,那么分区可以理解为在表目录下的又一级目录,这个目录的名字就是我们所定义的分区列的名字。

使用分区是为了加快数据查询速度设计的。

注意:分区列不是表里的某个字段,而是独立的列,我们根据这个列查询存储在表中的数据文件。

桶:简单来说,桶表就是把【大表】分成了【小表】。我们把表或者分区切分成桶表的主要目的:是为了获得更高的查询效率,尤其是抽样查询更加快捷。

桶表是 Hive 数据存储模型的最小单元。

当数据加载到桶表时,会对字段的值进行哈希取值,然后使用哈希值除以桶个数得到余数,按照余数进行分桶,保证每个桶中都有数据。

在物理上,每个桶表就是表或分区的一个文件。

倾斜数据:数据倾斜在 MapReduce 计算框架中经常发生。简单理解,该现象指的是在整个计算过程中,大量相同的 key 被分配到了同一个任务上,造成“一个人累死、其他人闲死”的状况,这违背了分布式计算的初衷,使得整体的执行效率十分低下。

正常数据:不用多说,这是我们做数据分析任务中使用到的有价值的数据文件。

理解 Hive 的数据存储模型对我们利用 Hive 进行开发有很大的帮助,因此,我们可以通过搭建 Hive 环境进行深入学习。

1.4 Hive 与数据库的比较

在1.3小节,我们提到了一个名词:数据仓库。由于 Hive 采用了类似 SQL 的查询语言 HQL(Hive Query Language),因此很容易将 Hive 理解为数据库。

其实从结构上来看,Hive 和数据库除了拥有类似的查询语言,再无类似之处。

我们先暂时从以下四个方面来阐述 Hive 和数据库的差异。数据库可以用在 Online 的应用中,但是 Hive 是为数据仓库而设计的,明白这一点,有助于从应用角度理解 Hive 的特性。

1.4.1 查询语言

由于 SQL 被广泛的应用在数据仓库中,因此,专门针对 Hive 的特性设计了类 SQL 的查询语言 HQL。

熟悉 SQL 开发,我们可以很方便的使用 Hive 进行开发。

1.4.2 数据更新

由于 Hive 是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive 中不建议对数据的改写,所有的数据都是在加载的时候确定好的。

而数据库中的数据通常是需要经常进行修改的,因此可以使用 INSERT INTO … VALUES 添加数据,使用 UPDATE … SET 修改数据。

1.4.3 执行延迟

Hive 在查询数据的时候,由于没有索引,需要扫描整个表,因此延迟较高。

另一个导致 Hive 执行延迟高的因素是 MapReduce 框架。由于 MapReduce 本身具有较高的延迟,因此在利用 MapReduce 执行 Hive 查询时,也会有较高的延迟。

相对的,数据库的执行延迟较低。当然,这个低是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候, Hive 的并行计算显然能体现出优势。

1.4.4 数据规模

由于 Hive 建立在 Hadoop 集群上并可以利用 MapReduce 进行并行计算,因此可以支持很大规模的数据;

对应的,数据库可以支持的数据规模较小。

1.5 Hive 的运行模式

Hive 的运行模式主要根据 MetaStore 数据库所在的位置进行区分的。主要有下面三种模式。我们先从理论方面进行学习,这三种模式安装方法将会在 Hive 环境搭建进行详细讲解。

1.5.1 内嵌模式

该模式使用的是内嵌的 Derby 数据库来存储元数据,不需要额外的 MetaStore 服务。数据库和 MetaStore 服务都嵌入在主 Hive Server 进程中。该模式配置简单,也是 Hive 默认选择的模式。

这种模式一次只能一个客户端连接,只适合用来实验,不适合用于生产环境。

1.5.2 本地模式

该模式主要采用外部数据库来存储元数据,目前支持的数据库有:MySQL、Postgres、Oracle、MS SQL Server。但使用 MySQL 较多。

该模式不需要单独启动 MetaStore 服务,用的是跟 Hive 在同一个进程里的 MetaStore 服务。也就是说,当我们启动一个 Hive 服务,里面默认会帮我们启动一个 MetaStore 服务。

那如何判断是不是该模式呢?Hive 会根据数据项:hive.metastore.uris 的参数值来判断,如果为空,则为本地模式。

1.5.3 远程模式

该模式需要单独起 MetaStore 服务,然后每个客户端都在配置文件里配置连接到该 MetaStore 服务。该模式的 MetaStore 服务和 Hive 运行在不同的进程里。

该模式适合用于生产环境。该模式下,需要配置属性项:hive.metastore.uris 参数来指定 MetaStore 服务运行的机器 ip 和端口,并且需要单独手动启动 MetaStore 服务。

我们第 1 章主要对 Hive 的产生背景、发展历史、优缺点基本知识点进行认识;重要的是要深入理解 Hive 的系统架构、运行机制、数据存储模型等知识点;还对 Hive 数据仓库和传统关系型数据库从四个方面进行了对比,要区分数据库和数据仓库的区别,最后我们对 Hive 的集中运行模式进行了简单了解。

下一章我们将会学习如何搭建 Hive 环境。

Baimi

世上只有两种编程语言:一种是总是被人骂的,一种是从来没人用的。

Baimi

世上只有两种编程语言:一种是总是被人骂的,一种是从来没人用的。