Hive的基本原理(一)

1. 前言

前面讲了很多关于集群搭建、以及HDFS和MapReduce的基本操作,接下来终于能学习新的内容了。。
Hive本身是数据仓库,那么什么是数据仓库呢?

数据仓库是为了协助分析报告,支持决策,为需要业务智能的企业提供业务流程的改进和指导,从而节省时间和成本,提高质量。它与数据库系统的区别是,数据库系统可以很好的解决事务处理,实现对数据的“增删改查”操作,而数据仓库则是用来查询分析的数据库,通常不会用来做单条数据的插入、修改和删除。

2. 什么是Hive

Hive是基于Hadoop构建的一套数据仓库分析工具,它提供了丰富的SQL查询方式来分析存储在Hadoop分布式文件系统中的数据。可以将结构化的数据文件映射为一张数据库表,并提供完整的SQL查询功能;也可以将SQl语句转化为MapReduce任务运行,通过SQl去查询分析需要的内容。这套类SQL简称为HQL,使对MapReduce不熟悉的用户利用HQL语言查询、汇总、分析数据,简化MapReduce代码,从而使用Hadoop集群。而MapReduce开发人员可以把自己写的Mapper和Reducer作为插件来支持Hive做更复杂的数据分析。

3. Hive和数据库的异同

Hive与传统的关系型数据库不同,虽然Hive提供了类SQL的查询语言(Hive Query Language),但是引入HQL的主要目的是为了降低学习成本,其底层还是MapReduce。Hive本身是数据仓库,并不是数据库系统。
Hive和数据库的主要区别在于:查询语言、存储位置、数据格式、数据更新、索引、执行、执行延迟、可扩展性和数据规模几方面:

区别 Hive RDBMS
查询语言 HQL SQL
数据存储位置 HDFS 本地文件系统
数据格式判断 查询时判断 插入时判断
执行 MapReduce Executor
执行延迟
处理数据规模

3.1 查询语言的区别

SQL语言到底和HQL语言有什么区别?

特性 HQL SQL
更新 UPDATE、INSERT、DELETE INSERT
事务 支持 有限支持
索引 支持 支持
延迟 亚秒级 分钟级
函数 数百个内置函数 几十个内置函数
多表插入 不支持 支持
Create table as select SQL-92不支持,有些数据库支持 支持
SELECT SQL-92 支持排序的SORT BY,可限制返回行数量的LIMIT
子查询 在任何子句中支持“相关”的或不相关的 只能在FROM、WHERE或HAVING子句中(不支持相关子查询)
视图 可更新 用户定义函数
扩展点 用户定义函数 MapReduce脚本

注意:SQL-92,是数据库的一个ANSI/ISO标准。它定义了一种语言(SQL)以及数据库的行为(事务、隔离级别等)。

3.2 数据存储位置的区别

在数据存储位置来说,Hive将所有的数据存储在HDFS中,并建立在Hadoop上;而数据库是将数据存储在块设备或本地文件系统中。

3.3 数据格式的区别

在Hive中,并没有定义特有的数据格式,数据格式是由用户指定的,用户在定义数据格式时需要指定3点属性:列分隔符(通常为空格、\t、\x001)、行分隔符(\n),以及读取文件数据的方法。

在加载数据的过程中,不需要从用户数据格式到Hive本身定义的数据格式进行转换,所以在Hive加载的过程中不会对数据本身做任何调整,而只是将数据内容简单的复制到相应的HDFS目录中。而在传统的数据空中,由于不同的数据库有不同的存储引擎,各自定义了相应的数据格式,全部的数据都会按照一定的组织结构进行存储,因此在加载数据的过程中会比较耗时。

3.4 数据更新的区别

Hive本身是针对数据仓库而设计的。数据仓库的内容往往是读多写少,所以Hive并不支持数据的修改和增加,所有的数据都是在加载的过程中完成的。而数据库中的数据往往需要经常进行修改、查询、增加等操作。

3.5 索引的区别

Hive在加载数据的过程中不会对数据做任何处理,也不会对数据进行扫描处理,所以也没有对数据中的某些键值创建索引。在Hive访问数据中满足条件的数据值时,需要扫描全部的数据,所以访问延迟较高。由于HQL最终会被转化成MapReduce,因此Hive可以进行并行访问数据,即使在没有索引的情况下,对于大批量数据的访问,Hive仍可以表现出优势。在数据库中,通常会针对某一列或某几列创建索引,所以对于少批量的满足特定条件的数据访问,数据库具有很高的效率,以及较低的延迟。
因此,Hive数据访问的延迟较高,不适合在线查询数据。

3.6 执行与执行延迟的区别

Hive中大多数查询的执行最终是通过MapReduce实现的,而数据库具有自己的执行引擎。由于Hive在查询数据的时候并没有建立索引,需要扫描整个表,由此造成的延迟较高。而且MapReduce自身也具有较高的延迟,这也会导致查询的效率。而相比较而言,在数据规模较小的情况下,数据库的执行延迟较低,只有当数据规模大到超过数据库的处理能力的时候,Hive的并行计算优势才会体现出来。

3.7 可扩展性的区别

Hive本身就是建立在Hadoop之上的,所以Hive的可扩展性的能力是和Hadoop是一致的。而数据库由于ACID语义的严格限制,扩展能力非常有限。
注:ACID是:Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)、Durability(持久性)。

3.8 处理数据规模的区别

很明显,Hive支持的数据规模要远远大于数据库本身。

4. Hive设计的应用

Hive主要应用于传统的数据仓库任务ETL(Extract-Transformation-Loading)和报表的生成。其中,报表生成中可以完成大规模数据分析和批处理的任务,进行海量数据离线分析和低成本进行数据分析,可以应用于日志分析。如统计网站一个时间段内的PV、UV,以及多维度数据分析等。

5. Hive的架构与基本组成

5.1 Hive的架构图

Hive的基本原理(一)
用户接口主要有3个,分别是CLI(Command Line)、Client、WUI。其中CLI是最常用的,在CLI启动时,一个Hive的副本也会随之启动。而Client是Hive的客户端,用户会连接至Hive Server,在启动Client模式时,需要指出Hive Server在哪个节点上,同时在该节点启动Hive Server。Web UI则是通过浏览器来访问Hive。

5.2 Hive的组件

5.2.1 Driver组件

核心组件,整个Hive的核心,该组件包括Complier、Optimizer和Executor,它的作用是将我们写的HQL语句进行解析、编译优化,生成执行计划,然后调用底层的MapReduce计算框架。

5.2.2 Metastore组件

Metastore主要用来存储元数据,Hive是将元数据存储在数据库中,如MySQL、derby。在Hive中的元数据包括表的名字、表的列和分区以及属性、表的属性(是否为外部表等)、表的数据所在目录等。通过指定METASTORE_PORT环境变量可以指定服务器监听的端口。

5.2.3 CLI

command line interface,命令行接口。也就是Shell环境,CLI启动的时候会同时启动一个Hive副本,这也是默认的服务。我们可以通过bin/hive或bin/hive --service cli命令来指出Hive Server所在的节点,并且在该节点启动Hive Server

5.2.4 ThriftServers

提供JDBC和ODBC接入的能力,它用来进行可扩展且跨语言的服务的开发,Hive集成了该服务,能让不同的编程语言调用Hive的接口。

5.2.5 Hive WEB Interface

Hive客户端提供了一种通过网页的方式访问Hive所提供的服务。这个接口对应Hive的HWI组件(Hive WEB Interface),默认端口是9999,在没有安装任何客户端软件的情况下,这个简单的Web接口可以代替CLI。另外,HWI是一个功能全面的Hadoop Web接口,其中包括运行Hive查询和浏览Hive mestore的应用程序。命令为:bin/hive --service hwi

5.3 Hive连接数据库的三种方式

Hive将元数据存储在RDBMS中,有三种模式可以连接到数据库。

5.3.1 单用户模式

此模式连接到In-memory的数据库Derby,一般用于Unit Test。

Hive的基本原理(一)

5.3.2 多用户模式

通过网络连接到一个数据库中,是最近常使用的连接方式。

Hive的基本原理(一)

5.3.3 远程服务器模式

用于非Java客户端访问元数据库,在服务器端启动MetaStoreServer,客户端利用Thrift协议通过MetaStoreServer访问元数据库。

Hive的基本原理(一)

6. Hive的执行流程

Hive的基本原理(一)
在Hive上执行查询操作时,大体流程如下:

  1. 用户提交查询任务到Driver。
  2. 编译器Compiler获得用户的任务计划。
  3. 编译器Compiler根据用户任务从Metastore中得到所需的Hive元数据信息。
  4. 编译器Compiler对任务进行编译,首先将HQL转换为抽象语法树,接着把抽象语法树转换成查询语句块,并将查询语句块转换为逻辑的查询计划。
  5. 把最终的计划提交到Driver。
  6. Driver将计划提交到Execution Engine,获得元数据信息,接着提交到JobTracker或者Source Manger运行该任务,该任务会直接从HDFS中读取文件并进行相应的操作。
  7. 取得并返回执行结果。