9.4 数据倾斜
要尽量减少数据倾斜.
9.4.1 合理设置 Map 数量
通常情况下,作业会通过input的目录产生一个或者多个map任务。
主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小。
是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。
应该减少 Map 数量 是不是保证每个map处理接近128m的文件块,就高枕无忧了?
答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。
应该增加 Map 数量
9.4.2 小文件合并
在 map 执行前合并小文件,减少 map 数:
CombineHiveInputFormat
具有对小文件进行合并的功能(系统默认的格式)。
HiveInputFormat
没有对小文件合并功能。
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
9.4.3 复制的文件文件增加 Map 数
当 input 的文件都很大,任务逻辑复杂,map 执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。
增加map的方法: 根据
computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
公式,调整maxSize
的值。让maxSize
低于blocksize
就可以增加 map 的个数。
执行查询, 查看 Map 的数量
select count(*) from emp;
设置
maxSize
的值, 然后再执行查询set mapreduce.input.fileinputformat.split.maxsize=100; select count(*) from emp;
9.4.4 合理设置 Reduce 个数
有 2 种方式可以设置 Reduce的个数
方法1: 动态计算
参数1: hive.exec.reducers.bytes.per.reducer
表示 Reduce 处理的最大数据量
参数2: hive.exec.reducers.max
每个 Job 最大的 Reduce 数量.
方法2: 直接指定
set mapreduce.job.reduces=5;
如果直接指定了具体的数量, 则不再动态的计算.
总结:
reduce个数并不是越多越好
过多的启动和初始化reduce也会消耗时间和资源;
另外,有多少个 reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置 reduce 个数的时候也需要考虑这两个原则:
- 处理大数据量利用合适的 reduce 数;
- 使单个 reduce 任务处理数据量大小要合适;