# 什么是Hive?
Hive是建立在 Hadoop 上的数据仓库基础构架。它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储、查询和分析存储在 Hadoop 中的大规模数据的机制。Hive 定义了简单的类 SQL 查询语言,称为 HQL,它允许熟悉 SQL 的用户查询数据。同时,这个语言也允许熟悉 MapReduce 开发者的开发自定义的 mapper 和 reducer 来处理内建的 mapper 和 reducer 无法完成的复杂的分析工作。
Hive 构建在基于静态批处理的Hadoop 之上,Hadoop 通常都有较高的延迟并且在作业提交和调度的时候需要大量的开销。因此,Hive 并不能够在大规模数据集上实现低延迟快速的查询,例如,Hive 在几百MB 的数据集上执行查询一般有分钟级的时间延迟。
#### Hive与关系数据库的区别
由于Hive采用了SQL的查询语言HQL,因此很容易将Hive理解为数据库。其实从结构上来看,Hive和数据库除了拥有类似的查询语言,再无类似之处。数据库可以用在Online的应用中,但是Hive是为数据仓库而设计的,清楚这一点,有助于从应用角度理解Hive的特性。
Hive和数据库的比较如下表:
![](https://box.kancloud.cn/bea461c0cfa14d82b69a0ebde943ff28_600x286.png)
#### Hive与Hadoop
Hive的执行入口是Driver,执行的SQL语句首先提交到Drive驱动,然后调用compiler解释驱动,最终解释成MapReduce任务去执行。
![](https://box.kancloud.cn/0cc4c5c76f5f2fbc7b91fd48edc0304d_497x332.png)
### Hive的服务端组件
1. Driver组件:该组件包括:Compiler、Optimizer、Executor,它可以将Hive的编译、解析、优化转化为MapReduce任务提交给Hadoop1中的JobTracker或者是Hadoop2中的SourceManager来进行实际的执行相应的任务。
2. MetaStore组件:存储着hive的元数据信息,将自己的元数据存储到了关系型数据库当中,支持的数据库主要有:Mysql、Derby、支持把metastore独立出来放在远程的集群上面,使得hive更加健壮。元数据主要包括了表的名称、表的列、分区和属性、表的属性(是不是外部表等等)、表的数据所在的目录。
3. 用户接口:CLI(Command Line Interface)(常用的接口:命令行模式)、Client:Hive的客户端用户连接至Hive Server ,在启动Client的时候,需要制定Hive Server所在的节点,并且在该节点上启动Hive Server、WUI:通过浏览器的方式访问Hive。
### Hive执行流程图:
![](https://box.kancloud.cn/971c28338915b714e1057fcd007a0e68_554x354.png)
#### 接收到一个sql语句后做的事情:
1.词法分析/语法分析
使用antlr将SQL语句解析成抽象语法树-AST
2.语义分析
从Megastore获取模式信息,验证SQL语句中队表名,列名,以及数据类型的检查和隐式转换,以及Hive提供的函数和用户自定义的函数(UDF/UAF)
3.逻辑计划生产
生成逻辑计划-算子树
4.逻辑计划优化
对算子树进行优化,包括列剪枝,分区剪枝,谓词下推等
5.物理计划生成
将逻辑计划生产包含由MapReduce任务组成的DAG的物理计划
6.物理计划执行
将DAG发送到Hadoop集群进行执行
7.将查询结果返回 ,流程如下图:
![](https://box.kancloud.cn/97a1c086a763816bd05536e798cb82eb_574x540.png)
### Hive编译过程
![](https://box.kancloud.cn/253554e48fbf0780057e40c72de41029_451x525.png)
### Hive数据模型
Hive没有专门的数据存储格式,用户可以自由的组织Hive中的表,只需要在创建表的时候告诉Hive数据中的列分隔符和行分隔符,Hive就可以解析数据。Hive中所有的数据都存储在HDFS中,存储结构主要包括数据库、文件、表和视图。Hive中包含以下数据模型:Table内部表,External Table外部表,Partition分区,Bucket桶。Hive默认可以直接加载文本文件,还支持sequence file 、RCFile。
#### 1.Hive数据库
类似传统数据库的DataBase,在第三方数据库里实际是一张表
简单示例命令行: create database test_database;
#### 2.内部表
Hive的内部表与数据库中的Table在概念上是类似。每一个Table在Hive中都有一个相应的目录存储数据。例如一个表tbInner,它在HDFS中的路径为/user/hive/warehouse/tbInner,其中/user/hive/warehouse是在hive-site.xml中由${hive.metastore.warehouse.dir} 指定的数据仓库的目录,所有的Table数据(不包括External Table)都保存在这个目录中。内部表删除时,元数据与数据都会被删除。
内部表简单示例:
创建数据文件:test_inner_table.txt
创建表:create table test_inner_table (key string);
加载数据:LOAD DATA LOCAL INPATH 'filepath' INTO TABLE test_inner_table;
查看数据:select * from test_inner_table;
删除表:drop table test_inner_table;
#### 3. 外部表
外部表指向已经在HDFS中存在的数据,并可以创建Partition。它和内部表在元数据的组织上是相同的,而实际数据的存储则有较大的差异。内部表的创建过程和数据加载过程这两个过程可以分别独立完成,也可以在同一个语句中完成,在加载数据的过程中,实际数据会被移动到数据仓库目录中;之后对数据对访问将会直接在数据仓库目录中完成。删除表时,表中的数据和元数据将会被同时删除。而外部表只有一个过程,加载数据和创建表同时完成(CREATE EXTERNAL TABLE ……LOCATION),实际数据是存储在LOCATION后面指定的 HDFS 路径中,并不会移动到数据仓库目录中。当删除一个External Table时,仅删除该链接。
外部表简单示例:
创建数据文件:test_external_table.txt
创建表:create external table test_external_table (key string);
加载数据:LOAD DATA INPATH ‘filepath’ INTO TABLE test_inner_table;
查看数据:select * from test_external_table;
删除表:drop table test_external_table;
#### 4.分区
Partition对应于数据库中的Partition列的密集索引,但是Hive中Partition的组织方式和数据库中的很不相同。在Hive中,表中的一个Partition对应于表下的一个目录,所有的Partition的数据都存储在对应的目录中。例如pvs表中包含ds和city两个Partition,则对应于ds = 20090801, ctry = US 的HDFS子目录为/user/hive/warehouse/pvs/ds=20090801/ctry=US;对应于 ds = 20090801, ctry = CA 的HDFS子目录为/user/hive/warehouse/pvs/ds=20090801/ctry=CA。
分区表简单示例:
创建数据文件:test_partition_table.txt
创建表:create table test_partition_table (key string) partitioned by (dt string);
加载数据:LOAD DATA INPATH ‘filepath’ INTO TABLE test_partition_table partition (dt=‘2006’);
查看数据:select * from test_partition_table;
删除表:drop table test_partition_table;
#### 5.桶
Buckets是将表的列通过Hash算法进一步分解成不同的文件存储。它对指定列计算Hash,根据Hash值切分数据,目的是为了并行,每一个Bucket对应一个文件。例如将user列分散至32个bucket,首先对user列的值计算Hash,对应Hash值为0的HDFS目录为/user/hive/warehouse/pvs/ds=20090801/ctry=US/part-00000;Hash值为20的HDFS目录为/user/hive/warehouse/pvs/ds=20090801/ctry=US/part-00020。如果想应用很多的Map任务这样是不错的选择。
桶的简单示例:
创建数据文件:test_bucket_table.txt
创建表:create table test_bucket_table (key string) clustered by (key) into 20 buckets;
加载数据:LOAD DATA INPATH ‘filepath’ INTO TABLE test_bucket_table;
查看数据:select * from test_bucket_table; set hive.enforce.bucketing = true;
#### 6.Hive的视图
视图与传统数据库的视图类似。视图是只读的,它基于的基本表,如果改变,数据增加不会影响视图的呈现;如果删除,会出现问题。如果不指定视图的列,会根据select语句后的生成。
示例:create view test_view as select * from test;
### Hive数据类型
Hive支持两种数据类型,一类叫原子数据类型,一类叫复杂数据类型。
1、原子数据类型包括数值型、布尔型和字符串类型,具体如下表所示:
![](https://box.kancloud.cn/097abaad8a98ed213b5f16e8ed12aedc_600x275.png)
由上表我们看到Hive不支持日期类型,在Hive里日期都是用字符串来表示的,而常用的日期格式转化操作则是通过自定义函数进行操作。
Hive是用Java开发的,Hive里的基本数据类型和java的基本数据类型也是一一对应的,除了String类型。有符号的整数类型:TINYINT、SMALLINT、INT和BIGINT分别等价于Java的Byte、Short、Int和Long原子类型,它们分别为1字节、2字节、4字节和8字节有符号整数。Hive的浮点数据类型FLOAT和DOUBLE,对应于Java的基本类型Float和Double类型。而Hive的BOOLEAN类型相当于Java的基本数据类型Boolean。对于Hive的String类型相当于数据库的Varchar类型,该类型是一个可变的字符串,不过它不能声明其中最多能存储多少个字符,理论上它可以存储2GB的字符数。
2、复杂数据类型包括数组(ARRAY)、映射(MAP)和结构体(STRUCT),具体如下所示:
![](https://box.kancloud.cn/a8a8f6f88bc1885b3400533f0b692b8f_600x276.png)