Hive调优(调优过程包括调整数据倾斜)

一个Hive查询生成多个map reduce job,一个map reduce job又有map,reduce,spill,shuffle,sort等多个阶段,所以针对hive查询的优化可以大致分为针对M/R中单个步骤的优化,针对M/R全局的优化,和针对整个查询(多M/R job)的优化。

Map阶段的优化,主要是确定合适的map数。那么首先要了解map数也就是切 片的计算公式,即:

块大小和切片的最大值求的最小值和最大切片求最大值。

在hive中min的默认值是1B,max的默认值是256MB

 

num_map_tasks = max[${mapred.min.split.size}, min(${dfs.block.size}, ${mapred.max.split.size})]

经过以上的分析,在设置map个数的时候,可以简单的总结为以下几点:
(1)如果想增加map个数,则设置mapred.map.tasks 为一个较大的值。
(2)如果想减小map个数,则设置mapred.min.split.size 为一个较大的值。
(3)如果输入中有很多小文件,依然想减少map个数,则需要将小文件merger为大文件,然后使用准则2。

Reduce阶段的优化

是指前面流程图中的reduce phase(实际的reduce计算)而非图中整个reduce task。Reduce阶段优化的主要工作也是选择合适的reduce task数量,跟上面的map优化类似。

reduce优化时,可以直接设置mapred.reduce.tasks参数从而直接指定reduce的个数。

Map与Reduce之间的优化

所谓map和reduce之间,主要有3道工序。首先要把map输出的结果进行排序后做成中间文件,其次这个中间文件就能分发到各个reduce,最后reduce端在执行reduce phase之前把收集到的排序子文件合并成一个排序文件。

 

第一个阶段中,由于内存不够,数据可能没办法在内存中一次性排序完成,那么就只能把局部排序的文件先保存到磁盘上,这个动作叫spill,然后spill出来的多个文件可以在最后进行merge。如果发生spill,可以通过设置io.sort.mb来增大mapper输出buffer的大小,避免spill的发生。另外合并时可以通过设置io.sort.factor来使得一次性能够合并更多的数据。调试参数的时候,一个要看spill的时间成本,一个要看merge的时间成本,还需要注意不要撑爆内存(io.sort.mb是算在map的内存里面的)。

 

关于文件从map端copy到reduce端,默认情况下在5%的map完成的情况下reduce就开始启动copy,这个有时候是很浪费资源的,因为reduce一旦启动就被占用,一直等到map全部完成,收集到所有数据才可以进行后面的动作,所以我们可以等比较多的map完成之后再启动reduce流程,这个比例可以通过mapred.reduce.slowstart. completed.maps去调整,他的默认值就是5%。如果觉得这么做会减慢reduce端copy的进度,可以把copy过程的线程增大。

文件格式的优化

 

文件格式方面有两个问题,一个是给输入和输出选择合适的文件格式,另一个则是小文件问题。小文件问题在目前的hive环境下已经得到了比较好的解决,hive的默认配置中就可以在小文件输入时自动把多个文件合并给1个map处理(当然,如果能直接读取大文件更好),输出时如果文件很小也会进行一轮单独的合并,所以这里就不专门讨论了。

关于文件格式,Hive中目前主要是3种,textfile,sequencefile和rcfile。总体上来说,rcfile的压缩比例和查询时间稍好一点,所以推荐使用。

Job整体优化

Job执行模式(本地执行v.s.分布式执行)、索引、Join算法、以及数据倾斜

Job执行模式

Hadoop的map reduce job可以有3种模式执行,即本地模式,伪分布式,还有真正的分布式。

但是实际上对于处理数据量非常小的job,直接启动分布式job会消耗大量资源,而真正执行计算的时间反而非常少。这个时候就应该使用本地模式执行mr job,这样执行的时候不会启动分布式job,执行速度就会快很多。

设置执行模式的主要参数有三个,一个是hive.exec.mode.local.auto,把他设为true就能够自动开启local mr模式。但是这还不足以启动local mr,输入的文件数量和数据量大小必须要控制,这两个参数分别为hive.exec.mode.local.auto.tasks.max和hive.exec.mode.local.auto.inputbytes.max,默认值分别为4和128MB,即默认情况下,map处理的文件数不超过4个并且总大小小于128MB就启用local mr模式。

Join算法

当两个表中有一个是小表的时候,就可以考虑用map join了,因为小表复制的代价会好过大表shuffle的代价。使用map join的配置方法有两种,一种直接在sql中写hint,语法是/*+MAPJOIN (tbl)*/,其中tbl就是你想要做replication的表。另一种方法是设置hive.auto.convert.join = true,这样hive会自动判断当前的join操作是否合适做map join,主要是找join的两个表中有没有小表。至于多大的表算小表,则是由hive.smalltable.filesize决定,默认25MB。但是在小表join大表的时候要考虑小表的记录的条目数,每个条目数占200字节,有时候可能大概80M的小表它的实际占用空间是1G多,会撑爆内存

数据倾斜

group by造成的倾斜和join造成的倾斜需要分开看。group by造成的倾斜有两个参数可以解决,一个是hive.map.aggr,默认值已经为true,意思是会做map端的combiner。

另一个参数是hive.groupby.skewindata。这个参数的意思是做reduce操作的时候,拿到的key并不是所有相同值给同一个reduce,而是随机分发,然后reduce做聚合,做完之后再做一轮MR,拿前面聚合过的数据再算结果

SQL整体优化

在hive生成的多个job中,在有些情况下job之间是可以并行的,典型的就是子查询。当需要执行多个子查询union all或者join操作的时候,job间并行就可以使用了。

设置job间并行的参数是hive.exec.parallel,将其设为true即可。默认的并行度最高为8,也就是允许sql中8个job并行。如果想要更高的并行度,可以通过hive.exec.parallel. thread.number参数进行设置,但要避免设置过大而占用过多资源。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://my.oschina.net/u/4085644/blog/3020150

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值