
1,前言
作为一名大数据开发相关工作的程序员,相信一定对hive这个技术组件不会陌生,这个组件自从Hadoop诞生之日起,便作为Hadoop生态体系(HDFS、MR/YARN、HIVE、HBASE)中极其重要的一员而存在,本人有幸在2012年初开始接触并在生产上使用大数据技术(Hadoop1.x),见证了hive从0.x版本到现在最新的3.x版本的一些列变化。本文将从一个使用者的角度,总结这些年来hive在使用中的一些心得。
2,什么是hive
相信百分之99%以上的童鞋都会说,hive不就是Hadoop生态体系中的分布式数据仓库吗。没错,这个是hive官方的定义,但是作为一个既有用过传统的数据仓库如:DB2,Teradata、Oracle使用经验,且也深度使用过hive的资深码农来说,我对这个定义并不太满意,因为它没有体现hive这个技术组件的特点,因为他跟传统的RDBMS数据仓库有很多的不一样,以下是我对hive特点的总结:
- 天然的分布式数据库,底层存储为HDFS(天然的分布式文件系统);
- 数据操作(查询、修改、条件删除)需要额外的计算引擎支持,如:MR、Tez、spark等;
- 虽然数据都是存储在HDFS,但是支持多种不同的数据存储格式,如:Text、SequenceFile、RCFile、avro、parquet、orc,carbondata等;
- 本身不支持索引功能,不支持时间复杂度非常低的数据结构;
- 所有操作(查询、修改、条件删除)基本上都是离线的,需要进行全表IO;
- 只是将数据与表之间建立一种简单的映射关系;
- 如果用SQL进行数据操作,将SQL转换为计算引擎的执行计划并执行。
于是,我对hive下的定义为:一个可以使用多种计算引擎以及兼容多种数据存储格式的分布式OLAP客户端。对,hive只是一个客户端而已(要知道hive最初诞生时是没有任何驻守的服务的,后来随着版本的升级,才出现了hive metastore和hive server以及后面的hive server2这两个对外提供连接功能的服务的)。因为他需要与额外的计算引擎支持,以及额外的数据格式支持,而且,这些计算引擎以及额外的数据格式是完全可以独立于hive之外而存在的。比如我的一张hive表底层的存储是text或者是parquet、orc等列式数据存储格式,这些数据存储格式其实都是自解释的,也就是说我不用hive这个外壳,也完全可以用其他api或者计算引擎把想要的数据给取出来。但是你想想,如果是传统的RDBMS数据库,它能做到这一点吗。
3,hive使用场景
项目中进行DB选择时,如果考虑用hive,必须要明白一点,也是最为核心的一点,hive是离线数据库,数据处理为离线的、离线的、离线的,重要事情说3遍!!!也就是说,当你向hive发起查询请求时,后台是需要调用计算引擎的,而启动计算引擎本身是需要花时间的,另外由于hive本身不支持索引(如B+tree等),这样就导致了查询时候需要对数据进行全量IO(也叫全表扫描),所以hive很慢(如果想更快呢,后续会讲如何优化得更快一点)。基于这两点就注定了hive只能用于离线的数据处理,那么hive的使用场景有哪些呢,我的总结如下:
- 面向大数据量、可持续写入的,静态的、结构化的、文本数据集;
- 一般作为业务数据的数据源,或者中间结果进行存储;
- 数据处理允许高延迟(至少都是分钟级),用于全量的数据分析;
- 数据一次写入,多次读取,后续不再(或极少)对数据进行修改(hive2.x之后可以支持对数据进行update,但是效率会很低,不太建议这样做);
以上是对hive使用场景的总结,另外对hive的优缺点总结如下:
优点:
- 因为数据完全是存在HDFS之上,存在数据冗余,因此数据支持高可用;
- 因为hive的数据存储几乎只占用磁盘空间(对比HBASE、Elasticsearch等内存消耗大户),而磁盘又是最廉价的硬件资源(相比CPU跟内存),适合来存储海量的全量离线数据集(轻松支持PB、TB量级数据集);
- 支持丰富的数据访问接口,如:JDBC,hiveserver以及主流的计算引擎spark、flink、storm等;
- 支持丰富的SQL语句(遵循SQL92标准),以及可根据业务情况定制的UDF函数;
- 表存储的数据是自解释的,可以完全脱离hive本身用其他api进行读取。
缺点:
- 数据处理延迟很高,因为每次数据处理都会启动计算引擎以及几乎全量的数据IO;
- 虽然也叫数据库,但是无法做到像RDBMS一样对事务的支持(虽然hive2.x开始号称也支持了,但是跟RDBMS的事务不是一个概念);
- 一旦写入,不支持修改(hive2.x之后,如果数据存储格式为ORC是支持修改的,但一般不建议)。
这部分的内容根据hive的特点来展开说明,相信大家对hive的特点已经有了一个比较明确的了解了,hive最大特点是什么呢,那就是:全量跟慢。针对慢这个特点,不仅广大的hive使用者感受到了,hive的创造者们也同样感受到了。于是乎,针对hive数据慢的特点,Apache社区做了哪些优化呢?
4,hive版本的进化
前面说到,因为hive在数据处理时需要:第一,启动计算引擎;第二,需要对存储的数据进行全量IO(全部扫描)。因为这两步,从而决定了hive的数据处理效率无论如何是快不了的,那么针对这两点,hive官方做了哪些改进呢?
- hive1.x版本开始,表支持动态分区和分桶功能(hive0.x是不支持该功能的)。
- 随着hive的升级,后续的hive版本(hive1.x之后)开始支持parquet,ORC、carbondata等带索引功能的列式存储格式;
- 自hive2.x开始支持LLAP(Live Long And Process)功能;
对于第一点:hive表增加分区分桶功能的本质目的是为了加快数据的操作(查询)速度,避免全量IO导致的性能损耗。比如你的数据查询根据日期进行,就可以将表根据:年、月、日、甚至小时进行多级分区,在查询时根据时间条件筛选就可以有效避免全量数据IO了,过滤掉跟查询日期无关的数据;

创建带多级分区的hive表
需要注意的是,分区字段必须是表中不存在但是数据中又必须存在的字段。如果是静态分区,需要数据写入时手动指定当前数据写到哪个分区中,而如果是动态分区的话(hive1.x版本需要手动开启,而hive3.x默认是开启的)则通过api动态写入就可以了。而对于分桶,需要指定一个表中存在的字段并事先确定桶的个数,然后数据在写入桶中时候,根据字段的hash值跟桶的数量进行取模,最终将数据根据该字段进行切片,将数据平均分配在各个桶中,一般在实际项目中用的确实不多,跟分区的目的一样,本质还是在数据操作时(查询)减少不必要的数据读取,减少数据IO。
对于第二点:随着hive版本的升级,hive支持越来越多的数据存储格式,最具有代表性的两种数据格式为:parquet、ORC,下表为这两张存储格式对对比:
功能 | parquet | orc |
开发语言 | Java | Java |
是否列式存储 | 是 | 是 |
复杂条件查询支持 | 支持 | 支持 |
数据压缩 | 支持多种数据压缩格式 | 支持多种数据压缩格式 |
ACID支持 | 不支持 | 支持 |
数据update | 不支持 | 支持 |
索引支持 | 支持粗粒度索引 | 支持粗粒度索引 |
计算引擎支持 | 主流计算引擎支持:spark,flink,mr,tez等 | 主流计算引擎支持:spark,flink,mr,tez等 |
另外附上,几个parquet与orc的性能测试对比图:

不同数据量写入时的速度对比

不同数据量占用的磁盘空间(采用同一压缩算法)

查询count(*)所花的时间对比
至于选用哪种数据存储格式,需要视你的使用场景来定了(似乎ORC的综合实力要更强一点)。但是有一点可以肯定的是,如非特殊情况,一定不要用text来存储你的hive数据,既占用存储空间不说,查询效率还低。
对于第三点:开启hive的LLAP模式(具体如何开启,请参考hive官方文档),之前说过我们每次对hive的数据进行处理(查询)时,都需要启动计算引擎,而在这个计算引擎在启动过程中是需要时间的(需要向资源管理器请求资源,然后还要初始化很多必要的环境变量等等),从而降低了整个数据处理的效率。而hive的LLAP模式则弥补了该缺陷。举一个hive查询的例子,在没有开启LLAP的情况下,如果我们用CLI的方式进行数据查询,后台默认用的是MR或者Tez计算引擎,如图所示:

默认设置Tez为hive的计算引擎
而如果设置用llap进行数据查询(set hive.llap.execution.mode=all),则看到的后台进程是这样的:

LLAP后台进程
除了可以在hive的CLI模式下使用LLAP外,用其他方式如,JDBC、hiveserver2等连接方式也是可行的,具体如何使用还是请各位参照官方文档,本章节内容不做展开。
5.总结
在项目的技术选型中如果对数据的要求为:全量、离线、高可用、一次写入多次读取。那么hive一定是非常适合的选择,另外如果想加速你数据处理的效率,可以从以下几个方面来考虑:
- 尽可能的使用分区,如果数据量特别大,建议使用多级分区;
- 因为业务原因而无法找到分区字段的,可以对数据进行分桶;
- 尽量使用带索引和数据压缩功能的数据格式来作为hive的底层存储;
- 如果集群资源允许(主要是内存资源),使用hive的LLAP功能;
虽然现在新版本的hive已经支持很多其他的数据格式,比如华为开源的carbondata(一种支持丰富索引功能的列式存储技术),但是在使用中会有很多意想不到的bug,不建议在生产环境中使用。在综合了效率、功能和稳定性,我推荐用ORC来作为hive的底层数据存储格式。
以上是我这些年来对hive使用的一点总结,希望对你有所帮助!
















