hive的优化

本文介绍了一系列针对Hive SQL查询的性能优化策略,包括减少数据处理量、优化join操作、调整reduce数量等方法,旨在帮助解决数据倾斜问题,提高大数据处理效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



优化:加快程序运行时间+无数据倾斜


数据倾斜的实质:key的分布不均匀


场景1:跑得慢


场景2:reduce执行到99%(或100%)卡住。查看任务界面,发现只有少量(1个或几个)reduce子任务未完成,因为其处理的数据量比其他reduce子任务处理的大。


技术&&数据:




1.尽量尽早的过滤数据,减少每个阶段的数据量,对于分区表要加分区,同时只选择需要使用到的字段


2.尽量原子化操作,尽量避免一个SQL包含复杂逻辑,可以使用中间表在上游并发处理复杂的逻辑


3.join操作,小表注意放在join的左边,否则会引起磁盘和内存的大量消耗


  1).使用mapjoin
  2).参数化调节:set hive.auto.convert.join=false;  (默认为true:高版本的hive自动检测加载表数据量,超过一定数据,自动加载到内存中)


4.只有一个reduce的场景 : 1.没有group by的汇总。2.order by。3.笛卡儿积。


5.尽量避免动态分区:


  动态分区需要设置的参数:set hive.exec.dynamic.partition=true;
                                      set hive.exec.dynamic.partition.mode=nonstrict;


6.使子查询并行执行:set hive.exec.parallel=true;


7.reduce的优化:


    1)减少reduce数量:小文件的处理:在map端合并数据,减少文件输出,相当于combiner:
            hive.map.aggr=true  (注:不适用于大表操作)
    2)离散化数据:
          (1)特例:NULL值 搞成随机数使其输入到不同的reduce中 
            (2) 参数化:hive.groupby.skewindata = true;
             当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group ByKey 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce中),最后完成最终的聚合操作


8.特殊情况特殊处理:在业务逻辑优化效果的不大情况下,有些时候可以将倾斜的数据单独拿出来处理。最后union回去;NULL不需要时不参与关联,需要时搞成随机数离散化




9.不同数据类型关联产生数据倾斜,尽量转换成同种类型


10.count distinct优化
优化前:select count(distinct id) from m


优化后: select count(1) from (select distinct id from m) tmp;
select count(1) from (select id from m group by id) tmp;


11.大表join大表性能调优:通过设置输入数据块的大小增加map数量


场景:观察执行过程,看到只生成2个map和一个reduce,感觉有问题


查找原因: 1.分别count(1)两张表对应的数据文件,发现两个文件大概在140MB左右。
     
          2.desc看了两张表的字段分别有20多个,10个字段。
 
分析:1.由于表字段数较少,且数据长度短,导致140多MB的文件已经能存储上千万行的数据。
   
      2.问题根源:HDFS中dfs.block.size默认设置为128MB.而当前的数据文件都是140MB左右,mr按照配置只能将140MB的文件拆分成2份(2个MAP)
 
      3.MAP数量不足,并导致行数不够,跑数缓慢。
 
解决方案:


      1.默认dfs.block.size=128MB这个设置不能系统级变更,随意修改后患无穷,只能从session级修改。
 
 2.在sessin中设置参数,如下:
    set hive.auto.convert.join=false #关闭map join
set dfs.block.size=64000000 #手动设置block size为64MB
set mapred.reduce.tasks=10 #手动设置让Reduce生产10个并行处理
 
 说明:设置参数后重跑任务,map数据升为9,reduce数量为10,并行度提高了N倍,同一个SQL从原来10min+跑不出又化成3min不到完成。






12.假设一个SQL任务:
 Select count(1) from popt_tbaccountcopy_mes where pt = ‘2012-07-04’;
 该任务的inputdir  /group/p_sdo_data/p_sdo_data_etl/pt/popt_tbaccountcopy_mes/pt=2012-07-04
 共有194个文件,其中很多是远远小于128m的小文件,总大小9G,正常执行会用194个map任务。
 Map总共消耗的计算资源: SLOTS_MILLIS_MAPS= 623,020
 我通过以下方法来在map执行前合并小文件,减少map数:
 set mapred.max.split.size=100000000;
 set mapred.min.split.size.per.node=100000000;
 set mapred.min.split.size.per.rack=100000000;
 set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
 再执行上面的语句,用了74个map任务,map消耗的计算资源:SLOTS_MILLIS_MAPS= 333,500
 对于这个简单SQL任务,执行时间上可能差不多,但节省了一半的计算资源。
 大概解释一下,100000000表示100M, 
 set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
 这个参数表示执行前进行小文件合并,
 
 前面三个参数确定合并文件块的大小,大于文件块大小128m的,按照128m来分隔,
 小于128m,大于100m的,按照100m来分隔,把那些小于100m的(包括小文件和分隔大文件剩下的),
 进行合并,最终生成了74个块。




————————————————


业务:











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值