前言
Hive是如何将SQL转换成MapReduce的?又是如何运行在不同的的执行引擎如:Mr,Tez,Spark?我们在工作时哪些地方需要进行优化?带着这些问题我们将开展一期实战的性能优化。
一、Hive中Map的个数是如何确定的?
原理:
默认情况下Map的个数为:目标文件的个数;文件的总大小totalSize/集群配置的总大小blockSize;
用户指定mapred.map.tasks,即用户期望的Map大小用expNum表示,但是计算引擎不会立即采纳,它会获取mapred.map.tasks与defaultNum的较大值用expMaxNum表示。
获取文件分片大小和分片个数,分片大小参数mapred.min.split.size;默认1和blockSize之间的较大值,用splitMaxSize表示,将目标文件或数据的总大小除以splitMaxSize即为真是的分片个数,用realSplitNum表示。
获取expMaxNum和realSplitNum较小的值为实际的map个数。
代码表达式如下:
defaultNum=totalSize/blockSize;
expNum=mapred.map.tasks;
expMaxNum=max(expNum,defaultNum);
splitMaxSize=totalSize/max(min.split.size,blockSize);
realSplitNum=min(expMaxNum,splitMaxSize)
二、如何修改Map个数?
理论
减少Map个数,需要增大mapred.min.split.size的值,减少set mapred.map.tasks的个数;
增大Map个数,需要减少mapred.min.split.size的值,增大set mapred.map.tasks的个数;
测试1:默认参数
set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;mapred.max.split.size=256000000; --公司集群默认值
set mapred.min.split.size=10000000; --公司集群默认值
set mapred.min.split.size.per.node=8000000; --每个节点处理的最小split
set mapred.min.split.size.per.rack=8000000; --每个机架处理的最小slit.
1.注意一般来说这四个参数的配置结果大小要满足如下关系。
max.split.size >= min.split.size >= min.size.per.node >= min.size.per.node
2.这四个参数的作用优先级分别如下
max.split.size <= min.split.size <= min.size.per.node <= min.size.per.node
select count(*) from dwd_level_info where dt>='2021-05-01' and dt<='2021-05-31' ;
测试2:增大Map的个数
set mapred.map.tasks=20;set mapred.min.split.size=100000000;
select count(*) from dwd_level_info where dt>='2021-05-01' and dt<='2021-05-31' ;
测试3:减小Map的个数
set mapred.map.tasks=5; set mapred.min.split.size=300000000;
select count(*) from dwd_level_info where dt>='2021-05-01' and dt<='2021-05-31' ;
总结
由此可见,虽然指定的mapred.map.tasks的个数,但是操作引擎不一定会认,需要结合mapred.max.split.size共同使用。有时候需要增大Map的个数目的是为了增大并发处理的能力,有时候需要减小Map的使用个数,目的为了减少磁盘IO操作,使用时结合场景使用。