Hive和并行数据仓库的比较

来源:互联网 发布:免费打电话软件 编辑:程序博客网 时间:2024/05/01 12:57

看到一篇比较Hive和并行数据仓库的比较文章(http://db3.javaeye.com/blog/807787),写得比较犀利,转载如下:

=============================================================

最近分析和比较了Hive和并行数据仓库的架构,本文记下一些体会。
Hive是架构在Hadoop MapReduce Framework之上的开源数据分析系统。 Hive具有如下特点:

1. 数据以HDFS文件的形式存储,从而可以很方便的使用外部文件
2. 元数据存储独立于数据存储之外,从而解耦合元数据和数据,同样的数据,不同的用户可以有不同的元数据
3. 查询计划被分解为多个MapReduce Job,并按照依赖关系依次执行,复用了MapReduce的执行架构
4. 灵活的存储格式,通过ObjectInspector将对数据列的访问与数据的具体存储格式解耦合,同一行数据在同一个数据处理流中可以以不同的格式出现
5. 基于规则的查询优化器,依次使用规则转换逻辑计划

下面,我们就把Hive跟传统的并行数据仓库进行一下深入的比较:

1. 存储引擎。 并行数据仓库需要先把数据装载到数据库中,按特定的格式存储成特定的页文件,然后才能查询;而Hive则不用装载数据,也不用格式转换,Hive内置了多种文件格式的支持,并且可以使用用户定制的格式实现(inputformat),这样大大节省了数据导入的开销。传统数据仓库是把数据导入系统中,而Hive则是动态的将对数据处理的逻辑(代码)导入系统中。

2. 执行引擎。Hive架构于MapReduce Framework之上,执行计划的灵活性较差,优化器可做的选择很少,例如:Join算法只有Grace Hash Join一种选择,性能更加优秀且稳定的Hybrid Hash Join则无法实现; Map端的Group-by算法只有Hash Group-by一种选择, Reduce端的Group-by只有sort group-by一种选择(不然MapReduce提供的sort就浪费了); limit无法和sort融合起来,很多情况下,用堆排序来融合limit与sort会更加高效。 Join, Group-by, Limit在OLAP,日志分析等任务中非常常用的Operator,而Hive在这3个Operator的实现上都依赖于MapReduce Frameowork提供的partition和sort,好处是实现比较简单,缺点是效率往往不是最优的。 然而,由于MapReduce数据处理流程的限制,效率更高的算法却无法实现。 相反,并行数据仓库实现了各种算法,它的查询优化器可以更加灵活的选择这3个Operator的不同实现。

3. 查询优化器。大多数商用数据仓库使用基于代价的优化器,在生成查询计划时,利用元数据中的统计信息估算每个operator要处理的数据量,选取代价较低的执行计划。不过,这些商用数据仓库的都起步于基于规则的查询优化器,而Hive正处于这样一个类似的起步阶段。因而Hive查询优化器能做的优化并不多,仅限于10几条转换规则。

4. 索引和缓冲管理。 对于查询来说,索引的作用至关重要,尽管Hive中的partition起到和索引类似的作用,但还比较初级,与并行数据仓库较为完善的索引(primary,secondary, clustered, unclustered)还有很大差距。 当然,Hive也没有缓冲区管理机制,只能依赖于文件系统的缓冲机制;并行数据仓库往往禁用操作系统的缓冲机制,针对不同的查询的特点设计了多种缓冲机制,从而优化了性能。

5. 并行扩展性。MapReduce将MR job的中间结果保存到Map Task的本地硬盘,从而MR Job的容错性非常好,Hive自然的利用了这一点;Hive执行计划中,每一个MapReduce job又把处理结果写到HDFS,从而又利用了HDFS的容错性。 这样,在一个Hive查询的执行中,如果某个节点出现故障了,只需要重新调度执行该节点的任务即可,不需要重新提交查询。 因此,Hive有非常好的intra-query fault-tolerance,所以可扩展性非常强,例如一个查询可以在4000个节点上同时跑;缺点是大大减少了pipeline parallelism的机会。 并行数据仓库往往采用的是pipeline架构,上游的Operator每产生一条数据就会送去下游的Operator。这样的好处是最大化了pipeline parallelism并避免了中间结果的磁盘读写,但是,当一个查询运行于并行数据库上时,一旦一个节点出现故障,并行数据仓库就必须重新执行该查询。所以,当一个集群中的单点故障发生率较高时,并行数据仓库的性能就会下降了。假设每个节点故障发生率是0.01%,那么1000个节点的集群中,单点故障发生率则为10%;假设每个节点故障发生率是0.0001%,那么5000个节点的集群中,单点故障发生率为0.5%!

6. 内存拷贝开销。 千万别小看这一点,内存拷贝会很大程度上拖累系统性能。 我们可以注意到,Hive中所有的哈希,比较,数值运算操作,都需要操作在Writable Object上,而每次重置(reset)这些Writable Object,都需要将数据从byte array拷贝到这些对象的byte[]成员中。 在更精巧的实现中,很多内存拷贝其实是可以避免的,并行数据仓库往往做了很多优化(甚至包含操作系统内核的优化,比如Teradata的PDE)去节省不必要的内存拷贝,从而又带来了性能提升。

在实际应用中,到底该选用Hive还是并行数据仓库,取决于这些:
1. 钱,Hive是开源的,并行数据仓库(db2, teradata, netezza, vertica)是非常昂贵的
2. 还是钱,Hive只需要普通机器集群,并且集群节点的操作系统和硬件都可以是异构的,单点故障发生率高也无所谓;并行数据仓库往往希望使用性能较高的服务器作为集群节点,从而单点故障发生率可以控制在一个非常低的范围。
3. 数据规模,如果是Google, Facebook, Baidu这种规模的应用,需要几千甚至上万节点的集群,目前的商业并行数据仓库产品就很难支撑了;如果是沃尔玛,eBay这些应用,并行数据仓库还是完全可以胜任的,并且性能会远优于Hive。

此文旨在抛砖引玉,欢迎大家进行更多的比较:-)

=============================================================

另补充我的一些观点:

Hive本意是在Hadoop的MapReduce编程模型上进行包装,使其支持声明式的SQL查询,其各种opr都是使用MapReduce模型模拟实现。这样的好处就是与Hadoop无缝融合,但是,MapReduce模型最适用的场景是聚集类的操作,即数据库中的Group By,其模型并不是为Join量身打造,即使能够通过设计实现Join操作,但是效率以及可选择性上也大大折扣,有点削足适履的感觉。

我觉得如果不拘束在MapReduce模型上,而是对于各种操作寻求最合适的模型而不是拘束在MapReduce模型上,但是充分吸收其Fault Tolerance的特性,可能会较好。

但是,Fault Tolerance的满足需要对中间结果进行物化,这与Pipeline又会矛盾。两者需要寻找一个平衡点。我觉得部分物化、部分Pipeline的方式也许是一种选择,类似于checkpoint。这样Fault Tolerance的粒度不是MapReduce模式下的单个操作,也不是Pipeline模式下的整个查询,而是居中,即查询中的子操作块。

总的感觉,Hive的工作更倾向于工程,而不是模式的创新。但是作为初级产品,还是很有意义的。

原创粉丝点击