Hive性能优化(新手重新标注版)

本文介绍了Hive查询性能优化的多个层面,包括调整MapReduce任务的split大小,使用压缩提高输出效率,创建SequenceFile和RCFile格式的表,并探讨了索引的创建、剪裁和使用。此外,还讲解了replication join和repartition join等优化策略,以及启用bucket map join和Sortedmerge选项来提升join操作的性能。
摘要由CSDN通过智能技术生成

以下是一个技术小白根据自己的理解能力在别人整理的基础上进行了一些重点标识和归纳。

一个Hive查询生成多个Map Reduce Job,一个Map Reduce Job又有Map,Spill,Shuffle,Sort,Reduce等多个阶段,所以针对Hive查询的优化可以大致分为针对MR中单个步骤的优化(其中又会有细分),针对MR全局的优化,和针对整个查询(多MR Job)的优化,下文会分别阐述。


在开始之前,先把MR的流程图帖出来(摘自Hadoop权威指南),方便后面对照。另外要说明的是,这个优化只是针对Hive 0.9版本,而不是后来Hortonwork发起Stinger项目之后的版本。相对应的Hadoop版本是1.x而非2.x。

Map阶段的优化(Map phase)(一般情况不做太多工作,意义不大。)
Map阶段的优化,主要是确定合适的Map数。那么首先要了解Map数的计算公式:
num_Map_tasks = max[${Mapred.min.split.size},
                min(${dfs.block.size},${Mapred.max.split.size})] 
  • Mapred.min.split.size 指的是数据的最小分割单元大小。
  • Mapred.max.split.size 指的是数据的最大分割单元大小。
  • dfs.block.size 指的是HDFS设置的数据块大小。
一般来说dfs.block.size这个值是一个已经指定好的值,而且这个参数Hive是识别不到的。 
所以实际上只有Mapred.min.split.size和Mapred.max.split.size这两个参数(本节内容后面就以min和max指代这两个参数)来决定Map数量。在Hive中min的默认值是1B,max的默认值是256MB:

所以如果不做修改的话,就是1个Map task处理256MB数据,我们就以调整max为主。通过调整max可以起到调整Map数的作用,减小max可以增加Map数,增大max可以减少Map数。需要提醒的是,直接调整Mapred.Map.tasks这个参数是没有效果的。
调整大小的时机根据查询的不同而不同,总的来讲可以通过观察Map task的完成时间来确定是否需要增加Map资源。如果Map task的完成时间都是接近1分钟,甚至几分钟了,那么往往增加Map数量,使得每个Map task处理的数据量减少,能够让Map task更快完成;而如果Map task的运行时间已经很少了,比如10-20秒,这个时候增加Map不太可能让Map task更快完成,反而可能因为Map需要的初始化时间反而让Job总体速度变慢,这个时候反而需要考虑是否可以把Map的数量减少,这样可以节省更多资源给其他Job。
Reduce阶段的优化(Reduce phase)
这里说的Reduce阶段,是指前面流程图中的Reduce phase(实际的Reduce计算)而非图中整个Reduce task。Reduce阶段优化的主要工作也是选择合适的Reduce task数量,跟上面的Map优化类似。
与Map优化不同的是,Reduce优化时,可以直接设置Mapred。Reduce.tasks参数从而直接指定Reduce的个数。当然直接指定Reduce个数虽然比较方便,但是不利于自动扩展。Reduce数的设置虽然相较Map更灵活,但是也可以像Map一样设定一个自动生成规则,这样运行定时Job的时候就不用担心原来设置的固定Reduce数会由于数据量的变化而不合适。
Hive估算Reduce数量的时候,使用的是下面的公式:
num_Reduce_tasks = min[${Hive.exec.Reducers.max},
                      (${input.size} / ${ Hive.exec.Reducers.bytes.per.Reducer})] 
也就是说,根据输入的数据量大小来决定Reduce的个数,默认Hive.exec.Reducers.bytes.per.Reducer为1G,而且Reduce个数不能超过一个上限参数值,这个参数的默认取值为999。所以我们可以调整Hive.exec.Reducers.bytes.per.Reducer来设置Reduce个数。
设置Reduce数同样也是根据运行时间作为参考调整,并且可以根据特定的业务需求、工作负载类型总结出经验,所以不再赘述。
Map与Reduce之间的优化(Spill, copy, Sort phase, 这部分是重点 )
Map phase和Reduce phase之间主要有3道工序。首先要把Map输出的结果进行排序后做成中间文件,其次这个中间文件就能分发到各个Reduce,最后Reduce端在执行Reduce phase之前把收集到的排序子文件合并成一个排序文件。这个部分可以调的参数挺多,但是一般都是不要调整的,不必重点关注。
Spill 与 Sort
在Spill阶段,由于内存不够,数据可能没办法在内存中一次性排序完成,那么就只能把局部排序的文件先保存到磁盘上,这个动作叫Spill,然后Spill出来的多个文件可以在最后进行merge。如果发生Spill,可以通过设置io.Sort.mb来增大Mapper输出buffer的大小,避免Spill的发生。另外合并时可以通过设置io.Sort.factor来使得一次性能够合并更多的数据。调试参数的时候,一个要看Spill的时间成本,一个要看merge的时间成本,还需要注意不要撑爆内存(io.Sort.mb是算在Map的内存里面的)。Reduce端的merge也是一样可以用io.Sort.factor。一般情况下这两个参数很少需要调整,除非很明确知道这个地方是瓶颈。
Copy
copy阶段是把文件从Map端copy到Reduce端。默认情况下在5%的Map完成的情况下Reduce就开始启动copy,这个有时候是很浪费资源的,因为Reduce一旦启动就被占用,一直等到Map全部完成,收集到所有数据才可以进行后面的动作,所以我们可以等比较多的Map完成之后再启动Reduce流程,这个比例可以通Mapred.Reduce.slowstart.completed.Maps去调整,他的默认值就是5%。如果觉得这么做会减慢Reduce端copy的进度,可以把copy过程的线程增大。tasktracker.http.threads可以决定作为server端的Map用于提供数据传输服务的线程,Mapred.Reduce.parallel.copies可以决定作为client端的Reduce同时从Map端拉取数据的并行度(一次同时从多少个Map拉数据),修改参数的时候这两个注意协调一下,server端能处理client端的请求即可。
文件格式的优化
文件格式方面有两个问题,一个是给输入和输出选择合适的文件格式,另一个则是小文件问题。小文件问题在目前的Hive环境下已经得到了比较好的解决,Hive的默认配置中就可以在小文件输入时自动把多个文件合并给1个Map处理,输出时如果文件很小也会进行一轮单独的合并,所以这里就不专门讨论了。相关的参数可以在这里找到。
关于文件格式,Hive0.9版本有3种,textfile,sequencefile和orcfile。总体上来说,orcfile的压缩比例和查询时间稍好一点,所以推荐使用。
关于使用方法,可以在建表结构时可以指定格式,然后指定压缩插入:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值