这些优化全是在公司中遇到瓶颈后的一些解决方案,精华部分,当然大数据时代任何问题的解决方法都不止一种,智者见智
slow相关参数能够设置map阶段执行完成在执行ruduce,默认值是0.05,设置成1后就会让map完全拿完数据了再执行reduce阶段,这样不会因为map端数据倾斜了执行map时也在执行reduce两个阶段的槽位都被占着,也就是内存利用率问题
set mapreduce.job.reduce.slowstart.completedmaps =1;
(数据应用)就像香肠,最好别看见它们是怎么做出来的。 ——Otto von Bismarck
作业优先级set mapred.job.priority=VERY_HIGH;
stage-label.sql中小文件太多,还比较小,几k大小的数据,最多一次一个job产生了9万多个map,100个reduce
第一条sql:
设置reduce数无效,合并map无效,压缩无效,最后设置bzip2压缩有点效果,因为bzip2支出文件切分,但是cpu会很吃力,毕竟一小时有1-2T的数据量
我决定废弃gzip和bzip2,使用DeflateCodec(只是在stage-label.sql中)
解决办法:
1.在这个脚本中有很多条sql,我采用优化sql,在where条件中不能加别名,有的sql为了给一个type字段过滤就在一个大表查询中加了嵌套,
废弃嵌套,把用函数处理后的字段放在where后不加别名
2.有的sql不产生reduce,在where后加distribute by rand(1234),强制产生reduce,在加上mapred.reduce.tasks参数
3.加上压缩属性:set hive.exec.compress.output=true;
set mapred.output.compress=true;
set mapred.output.compression.type=BLOCK;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.DeflateCodec;
set mapred.reduce.tasks=50;
65.5g跑出来到目标表,24.5g,DeflateCodec压缩后8.5g,压缩比大约35%
第二条sql:
以上一条sql目标表为源表向另一张表插入数据,文件不切分,即使是压缩文件,map执行前也没有解压文件,因为就产生了50个map,依然是没有reduce阶段。
产生了几十个小文件(kb大小),显然在一个脚本中设置全局reduce不合理
解决办法:
1.getEc这个udf函数中:如果传入的参数是null,返回空字符串,如果是'null',不处理,可以也返回空字符串(暂不优化),把where ec is null去掉,
然后把嵌套去掉,直接把udf处理后的字段放在where后过滤,然后把udf处理的字段 !='',改成传入的参数 != '',如此一来少调用了udf,少了where条件,
少了嵌套(少了一部大数据量的查询)
2.让其强制产生reduce,并再次设置reduce数量(用于覆盖第一次设置的reduce数量属性):set mapred.reduce.tasks=1;
有效果,确实会合并小文件,看来defalteCodec也是可以合并的,但是reduce阶段比较慢,猜测是反序列化后合并在做压缩导致的
又测试了下不压缩只覆盖reduce数量参数,reduce阶段确是会快很多,只需要反序列化即可:(还是没有改压缩方式,默认压缩,效率也还行)
set mapreduce.reduce.tasks=1;
distribute by rand(1);
第三条sql:
待优化:
use db;
in