一、Hive介绍和架构
Hive 是基于Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供完整的SQL查询功能,可以将SQL语句转换为MapReduce任务进行运行。其优点是学习成本低,可以通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库的统计分析。
Hive 是建立在Hadoop上的数据仓库基础构架。它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储、查询和分析存储在Hadoop中的大规模器数据的机制。Hive定义了简单的类SQL查询语言,称为HQL,它允许熟悉SQL的用户查询数据。同时,这个语言也允许熟恶MapReduc开发者开发自定义的mapper和reducer来处理内建的mapper 和reducer来处理内建的mapper和reducer无法完成的、复杂的分析工作。
1.Hive 与关系数据库的区别
(1) Hive 和关系数据库存储文件的系统不同,Hive 使用的是Hadop 的HDFS(Hadoop 的分布式文件系统),关系数据库则是服务器本地的文件系统。
(2) Hive 使用的计算模型是MapReduce,而关系数据库则是自己设计的计算模型。
(3) 关系数据库都是为实时查询的业务进行设计的,而Hive 则是为海量数据做数据挖掘设计的,实时性很差; 实时性的区别导致Hive 的应用场景和关系数据库有很大的不同。
(4) Hive 很容易扩展自己的存储能力和计算能力,这个是继承Hadoop的,而关系数库在这个方面要比Hive 差很多。
2.Hive 架构介绍
架构图如下:
Hive 的体系结构可以分为以下几部分:
(1) 用户接口主要有三个: CLI Client 和WUI。其中最常用的是CLI,CLI 启动的的候,会同时启动一个Hive 副本。Client 是Hive 的客户端,用户连接至Hive Server。在启动Client 模式的时候,需要指出Hive Server 所在节点,并且在该节点启动Hive Server。WUL是通过浏览器访问Hive 的。
(2) Hive 将元数据存储在数据库中,如MySQL、Derby。Hive 中的元数据包括表的名子、表的列、表的分区、表的属性(是否为外部表等)、表的数据所在目录等。
(3)解释器、编译器、优化器完成HOL 查询语句。生成的查询计划存储在HDFS 中,并在随后有MapReduce 调用执行。
(4)Hive的数据存储在HDFS中,大部分的查询、计算由MapReduce 完成(包含的*查询。比如select * from 不会生成MapReduce任务)。Hie将元数据存储在RDBAS中。
二、Hive 数据类型和表结构
Hive的内置数据类型可以分为两大类:
1)基础数据类型
2)复杂数据类型
1、基础数据类型
基础数据类型包括:TINYINT、SMALLINT、INT、BIGINT、BOOLEAN、FLOAT、DOUBLE、STRING、BINARY、TIMESTAMP、DECIMAP、CHAR、VARCHAR、DATE。Hive基础数据类型如图所示,下面的表格列出这些基础类型所占的字节以及Hive从什么版本开始支持这些类型。
2、复杂数据类型
复杂类型包括:ARRAY、MAP、STRUCT、UNION,这些复杂类型是由基础类型组成的。
(1)ARRAY: ARRAY 类型是由一系列相同数据类型的元素组成,这些元素可以通过下表来访问。t比如有一个ARRAY 类型的变量fruits,它是由[‘apple','orange','mango']组成,那么我们可以通过fruits[1]来访问元素orange,因为ARRAY 类型的下标是从0开始的。
(2) MAP:MAP 包含key->value 键值对,可以通过key 来访问元素。例如: 访问元素,假设是个map类型,其中username是key
,pssword 是value; 那么我们可以通过userlist['username']来得到这个用户对应的passwod。
(3) STRUCT:STRUCT可以包含不同数据类型的元素,可以通过“点语法”的方式来得到所需要的元素,比如user是一个STRUCT类型,那么可以通过user.address得到这个用户的地址。
(4) UNION:UNONTYPE这个数据类型是从Hive0.7.0 开始支持的。
3、内部表和外部表的区别
1)创建表时:Hive默认创建的是内部表,创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径, 不对数据的位置做任何改变。
2)删除表时:在删除表的时候,内部表的元数据和数据会被一起删除, 而外部表只删除元数据,不删除数据。这样外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。
三、Hive分区、桶与倾斜
1、Hive的分区
(1) 在Hive Select 查询中一般会扫描整个表内容,会消耗很多时间做没必要的工作。有时候查询只需要描表中关心的一部分数据,因此建表时引入了patition概念。
(2)分区表指的是在创建表时指定的partition 的分区空间。
(3) 如果需要创建有分区的表,需要在create 表的时候调用可选参数partitioned by,详见表创建的语法结构。
(4) 一个表可以拥有一个或者多个分区,每个分区以文件夹的形式单独存储在表文件夹的目录下。
(5) 表和列名不区分大小写。
6) 分区是以字段的形式在表结构中存在,通过describe table 命令可以查看到字段存在,但是该字段不存放实际的数据内容,仅仅是分区的表示。
2、Hive桶表
分桶其实就是把大表化成了“小表”,然后通过两个表相同列使用Map 端连接(Map-Side Join),这是用来解决大表与小表之间的连接问题。将桶中的数据按某列进行排序会提高查询效率。
(1)创建分桶表
(2)数据导入
(3)小结:分桶适合于sampling,不过其数据正确地导入到 Hive表中,需要用户自己来保证,因为table中信息仅仅是元数据,而不影响实际填充表到命令。
3、Hive的数据倾斜
(1) 数据倾斜的原因
使map的输出数据更均匀地分布到Reduce 中,是我们的最终目标。由于Hash 算法的局限性,按 key Hash会或多或少地造成数据倾斜。大量经验表明数据倾斜的原因是人为的建表疏忽或业务逻辑,是可以规避的。
(2) 解决思路
Hive的执行是分阶段的,map 处理数据量的差异取决于上一个stage 的rduce输出,所以如何将数据均匀地分配到各个reduce 中,就是解决数据倾斜的根本所在。
(3) 具体办法
内存优化和IO 优化。
驱动表: 使用大表做驱动表,以防止内存滥出; Join 最右边的表是驱动表: Mapjoin无视join 顺序,用大表做驱动表。
4、Mapjoin是一种避免数据倾斜的手段
(1) 允许在map阶段进行join操作,MapJoin把小表全部读入内存中,在map阶段直接拿另外一个表的数据和内存中表数据做匹配。由于对map进行了join操作,省去了reduce运行,效率也会高很多。(2) 在对多个表join连接操作时,将小表放在join的左边,大表放在jion的右边。在执行这样的join 连接时,小表中的数据会被缓存到内存当中,这样可以有效减少发生内存溢出错误的几率。
一、设置参数
hive.map.aggr = true
hive.groupby.skewindata=true
二、SQL语言调节
比如:在group by纬度过小时,采用 sum() group by 的方式来替换 count(distinct)完成计算。
三、Stream Table
将在 reducer中进行join操作时的小table放入内存,而大table通过stream方式读取。
四、索引
Hive从0.80开始才有索引,它提供来一个Bitmap位图索引,索引可以加快 group by 查询语句的执行速度,但用得较少。
四、环境搭建
参考笔者博客:Hive环境搭建