文章目录
- 1. 分区
- 2. 优先级问题
- 3. 连接问题
- 4. SQL的执行顺序的问题
- 5. 左右连接驱动表的问题
- 6. 多表连接
- 7. 内连接和笛卡尔积 【笛卡尔积只有一个reduce很慢】
- 8. distinct+join问题
- 9. in/exists子查询问题
- 10. 子查询问题
- 11. 查询字段加快速度的方法
- 12. 慎用order by
- 13. 压缩+设置reduce+设置group
- 14. group和union的问题
- 15. case when then 和子查询
- 16. count+distinct问题
- 17. join和exists问题
- 18. case when then 判断不同条件进行分组求count
- 19. 并行执行JOB
- 20. 使用本地MR
- 21. 避免数据倾斜
- 22. 控制Map 和 Reduce的数量
- 23. 中间结果压缩
- 24. 杀手锏
- 25. 参数理解优化整理
1. 分区
通过限定分区来限定扫描的范围, 查询一定要指定分区, 否则会全表扫描的
2. 优先级问题
() > not > and > or
3. 连接问题
- 只支持等值连接,不支持非等值连接
- 内连接小表放前面,大表放后面
- 连接小表可以使用mapjoin
小表可以放进内存当中【维度表、或者行数<2w】
小表是不能作为驱动表的【比如left join的左表】select /*+MAPJOIN(b)*/ a.k, a.v from a join b on a.k = b.k
4. SQL的执行顺序的问题
- from -> join -> where -> group -> 聚合函数 -> having -> 算数函数 -> select -> distinct -> order
- 既然是这样子的话,那么我们的sql在书写的时候就要注意在join之前过滤下数据
select a.x,b.x from a full|left|right outer join b on (a.key=b.key and a.ds=d1 and b.ds=d1)
改写成
Select t1.x ,t2.x from (select * from a where ds=d1) t1
full outer join (select * from b where ds=d1) t2 on t1.key=t2.key
5. 左右连接驱动表的问题
- 驱动表的过滤条件放在on中会存在问题,应该在left join之前或者之后进行过滤
select a.x,b.x from a left outer join b on (a.key=b.key and a.ds=d1 and b.ds=d1)
应该写成
select a.x ,b.x from a
left outer join b on a.key=b.key and b.ds=d1
where a.ds=d1
或者
select t1.x ,t2.x from (select * from a where ds=d1) t1
Left outer join b t2 on t1.key=t2.key and t2.ds=d1
6. 多表连接
select
*
from a
join b
on a.k = b.k
join c
on c.k = b.k
7. 内连接和笛卡尔积 【笛卡尔积只有一个reduce很慢】
--这是内连接
select
*
from
a join b
on a.k = b.k
-- 这句话在MySQL或者oracle等价内连接,但是在hive就是笛卡尔积
-- 只有连接条件时不等式是才可使用笛卡尔积!
select * from a, b where a.k = b.k
8. distinct+join问题
如果一张表应该是distinct的,但是实际上却不是这样。那么我们要先distinct放到子查询中然后在进行join!
9. in/exists子查询问题
- 不支持in后面的子查询,但是可以是列表。如province in (‘gd’,’gx’)
- 通过 semi join实现 【半连接-就是说join到之后返回a表记录,且只返回一次】
SELECT a.key, a.value FROM a WHERE a.key in (SELECT b.key FROM B)
可以写成:
SELECT a.key, a.val FROM a LEFT SEMI JOIN b on (a.key = b.key)
10. 子查询问题
- from后面支持子查询,where后面不支持子查询
11. 查询字段加快速度的方法
- 如果where 里面没有除了分区外的过滤条件,使用 * 不用生成map/reduce可以加快速度。
12. 慎用order by
- 全局排序,只有一个reduce
13. 压缩+设置reduce+设置group
- 结果压缩:(默认不压缩)
set hive.exec.compress.output=true;
- 压缩算法:(这个一般不用设,默认是gzip)
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
- 特殊情况下设置reduce的个数
set mapred.reduce.tasks=n
- 数据严重倾斜时在sql前面加上
set hive.groupby.skewindata = true
-- 数据严重倾斜通常发生在 group by,其中维度值少,维度对应的记录数特别大的时候。
14. group和union的问题
先group然后进行union的话,会每一个group启动一个MR任务,然后在进行汇总。性能非常低下!
如果先union然后进行group的话,性能就会提升很多!
15. case when then 和子查询
使用case when then来代替子查询可以减少job数量,优化效率很高!
16. count+distinct问题
例句1:
SELECT
COUNT(DISTINCT uin) login_uins
FROM
tabled
WHERE
ftime >= 20121001
AND ftime <= 20121001
例句2:
SELECT
COUNT(uin) login_uins
FROM
( select distinct uin from tabled WHERE
ftime >= 20121001
AND ftime <= 20121001 ) subq
- 例句1虽然只有1个mr,但是,这个mr却只有1个reduce任务,导致这个reduce任务需要读取和处理大量的数据,这不仅导致执行慢,而且,在如果tabled中的数据量太大,可能导致执行reduce任务的节点down掉。
- 例句2先去重,后全局统计,没有像例句1那样明显的瓶颈。所以,请牢记当对某个数据集进行全局count distinct操作时,尽量用例句2的形式。
- 在其他情况下,即使有group by,但是group by的维度太低,也可以考虑这种改写方法。也就是说,一定要避免group by的维度太低。
17. join和exists问题
-- NOT EXISTS使用left outer join加 is null实现的:
select …
from a
where …
and not exists(select 1 from b where a.col1=b.col2 and b.col3=… and…)
等价于
select …
from a
left outer join b
on a.col1=b.col2
and b.col3=…
and …
where …
and b.col2 is null
-- 使用left simi join实现exists:
select …
from a
where …
and exists(select 1 from b where a.col1=b.col2 and b.col3=… and…)
等价于
select …
from a
left semi join b
on a.col1=b.col2
and b.col3=… and …
18. case when then 判断不同条件进行分组求count
select
platform
,version
,channel
,count(case when lose_user = '1' then qimei end) as lose_user
,count(case when will_lose = '1' then qimei end) as will_lose_user
from 表
where ds=...
and (lose_user = '1' or will_lose = '1')
group by
platform
,version
,channel
19. 并行执行JOB
set hive.exec.parallel=true; //打开任务并行执行
set hive.exec.parallel.thread.number=16; //同一个sql允许最大并行度,默认为8。
20. 使用本地MR
set hive.exec.mode.local.auto=true; //开启本地mr
//设置local mr的最大输入数据量,当输入数据量小于这个值的时候会采用local mr的方式
set hive.exec.mode.local.auto.inputbytes.max=50000000;
//设置local mr的最大输入文件个数,当输入文件个数小于这个值的时候会采用local mr的方式
set hive.exec.mode.local.auto.tasks.max=10;
当这三个参数同时成立时候,才会采用本地mr
21. 避免数据倾斜
数据倾斜可是性能的一大杀手。
21.1 症状
- 任务迚度长时间维持在99%(或100%);
- 查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成。
- 本地读写数据量很大。
21.1 原因
- key分布不均匀
- GROUP BY
- COUNT DISTINCT
- join
21.1 解决方案
- group by
使用Hive对数据做一些类型统计的时候遇到过某种类型的数据量特别多,而其他类型数据的数据量特别少。当按照类型进行group by的时候,会将相同的group by字段的reduce任务需要的数据拉取到同一个节点进行聚合,而当其中每一组的数据量过大时,会出现其他组的计算已经完成而这里还没计算完成,其他节点的一直等待这个节点的任务执行完成,所以会看到一直map 100% reduce 99%的情况。
set hive.map.aggr=true
set hive.groupby.skewindata=true
hive.map.aggr=true 这个配置项代表是否在map端进行聚合
hive.groupby.skwindata=true 当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。
- map和reduce优化
当出现小文件过多,需要合并小文件。可以通过set hive.merge.mapfiles=true来解决。
单个文件大小稍稍大于配置的block块的大小,此时需要适当增加map的个数。解决方法:set mapred.map.tasks=个数
文件大小适中,但reduce端计算量非常大,如select id,count(*),sum(case when…),sum(case when…)…需要增加map个数。解决方法:set mapred.map.tasks=个数,set mapred.reduce.tasks=个数
- count(distinct)
如果数据量非常大,执行如select a,count(distinct b) from t group by a;类型的SQL时,会出现数据倾斜的问题。
解决方法:使用sum…group by代替。如select a,sum(1) from (select a, b from t group by a,b) group by a;
- 大表和一个小表进行join
解决方法:使用mapjoin 将小表加载到内存中。
如:select /*+ MAPJOIN(a) */
a.c1, b.c1 ,b.c2
from a join b
where a.c1 = b.c1;
- 关联字段有数据为空
select * from log a
join users b
on a.id is not null and a.id = b.id
union all
select * from log a
where a.id is null;
select * from log a
left outer join users b
on
case when a.user_id is null
then concat(‘hive’,rand() )
else a.user_id end = b.user_id;
22. 控制Map 和 Reduce的数量
22.1 控制map数量
22.1.1 map数量的计算
- 主要的决定因素有: input的文件总个数,input的文件大小,集群设置的文件块大小(目前为128M, 可在hive中通过set dfs.block.size;命令查看到,该参数不能自定义修改);
- 假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(6个128m的块和1个12m的块),从而产生7个map数
- 假设input目录下有3个文件a,b,c,大小分别为10m,20m,130m,那么hadoop会分隔成4个块(10m,20m,128m,2m),从而产生4个map数
- 如果文件大于块大小(128m),那么会拆分,如果小于块大小,则把该文件当成一个块。
22.1.2 是不是map越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。
22.1.3 是不是保证每个map处理接近128m的文件块,就高枕无忧了?
答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。
22.1.4 如何合并小文件,减少map数?
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
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个块。
22.1.5 如何适当的增加map数?
当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。
select data_desc,
count(1),
count(distinct id),
sum(case when …),
sum(case when …),
sum(…)
from a group by data_desc
如果表a只有一个文件,大小为120M,但包含几千万的记录,如果用1个map去完成这个任务,肯定是比较耗时的,这种情况下,我们要考虑将这一个文件合理的拆分成多个,
这样就可以用多个map任务去完成。
set mapred.reduce.tasks=10;
create table a_1 as
select * from a
distribute by rand(123);
这样会将a表的记录,随机的分散到包含10个文件的a_1表中,再用a_1代替上面sql中的a表,则会用10个map任务去完成。
每个map任务处理大于12M(几百万记录)的数据,效率肯定会好很多。
看上去,貌似这两种有些矛盾,一个是要合并小文件,一个是要把大文件拆成小文件,这点正是重点需要关注的地方,
根据实际情况,控制map数量需要遵循两个原则:使大数据量利用合适的map数;使单个map任务处理合适的数据量;
22.2 控制reduce数量
22.2.1 Hive怎么确定reduce的个数
reduce个数的设定极大影响任务执行效率,不指定reduce个数的情况下,Hive会猜测确定一个reduce个数,基于以下两个设定:
hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量,默认为1000^3=1G)
hive.exec.reducers.max(每个任务最大的reduce数,默认为999)
计算reducer数的公式很简单N=min(参数2,总输入数据量/参数1)
即,如果reduce的输入(map的输出)总大小不超过1G,那么只会有一个reduce任务;
如:select pt,count(1) from popt_tbaccountcopy_mes where pt = ‘2012-07-04′ group by pt;
/group/p_sdo_data/p_sdo_data_etl/pt/popt_tbaccountcopy_mes/pt=2012-07-04 总大小为9G多,因此这句有10个reduce
22.2.2 调整reduce个数的方法
set hive.exec.reducers.bytes.per.reducer=500000000; (500M)
select pt,count(1) from popt_tbaccountcopy_mes where pt = ‘2012-07-04′ group by pt; 这次有20个reduce
set mapred.reduce.tasks = 15;
select pt,count(1) from popt_tbaccountcopy_mes where pt = ‘2012-07-04′ group by pt;这次有15个reduce
22.2.3 reduce个数是不是越多越好?
同map一样,启动和初始化reduce也会消耗时间和资源;另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题
22.2.4 什么情况下只有一个reduce
很多时候你会发现任务中不管数据量多大,不管你有没有设置调整reduce个数的参数,任务中一直都只有一个reduce任务;
其实只有一个reduce任务的情况,除了数据量小于hive.exec.reducers.bytes.per.reducer参数值的情况外,还有以下原因:
1 没有group by的汇总,比如把select pt,count(1) from popt_tbaccountcopy_mes where pt = ‘2012-07-04′ group by pt; 写成 select count(1) from popt_tbaccountcopy_mes where pt = ‘2012-07-04′;
2 用了Order by
3 有笛卡尔积
通常这些情况下,除了找办法来变通和避免,暂时没有什么好的办法,因为这些操作都是全局的,所以hadoop不得不用一个reduce去完成;
同样的,在设置reduce个数的时候也需要考虑这两个原则:使大数据量利用合适的reduce数;使单个reduce任务处理合适的数据量;
23. 中间结果压缩
23.1 中间Lzo,最终Gzip
set mapred.output.compress = true;
set mapred.output.compression.codec = org.apache.hadoop.io.compress.GzipCodec;
set mapred.output.compression.type = BLOCK;
set mapred.compress.map.output = true;
set mapred.map.output.compression.codec = org.apache.hadoop.io.compress.LzoCodec;
set hive.exec.compress.output = true;
set hive.exec.compress.intermediate = true;
set hive.intermediate.compression.codec = org.apache.hadoop.io.compress.LzoCodec;
23.2 中间Lzo,最终结果不压缩
set mapred.output.compress = true;
set mapred.output.compression.codec = org.apache.hadoop.io.compress.LzoCodec;
set mapred.output.compression.type = BLOCK;
set mapred.compress.map.output = true;
set mapred.map.output.compression.codec = org.apache.hadoop.io.compress.LzoCodec;
set hive.exec.compress.intermediate = true;
set hive.intermediate.compression.codec = org.apache.hadoop.io.compress.LzoCodec;
24. 杀手锏
- 在MapReduce的WEB界面上,关注Hive Job执行的情况;
- 了解HQL -> MapReduce的过程;
- HQL优化其实也是MapReduce的优化,作为分布式计算模型,其最核心的地方就是要确保每个节点上分布的数据均匀,才能最大程度发挥它的威力,否则,某一个不均匀的节点就会拖后腿。
25. 参数理解优化整理
25.1 container是什么?
Yarn Container就是一个yarn的java进程, 在Mapreduce中的AM,MapTask,ReduceTask, spark的driver和executor等等都作为Container在Yarn的框架上执行,你可以在RM的网页上看到Container的状态。
25.2 相关参数
- Yarn
(1) yarn.scheduler.minimum-allocation-mb 最小容器内存,默认1024M
(2) yarn.scheduler.maximum-allocation-mb 最大容器内存,默认8192M
(3) yarn.nodemanager.vmem-pmem-ratio 物理内存与虚拟内存比值,默认2.1,即为使用1G物理内存可以使用2.1G虚拟内存,生产环境中一般会调整大一些,具体虚拟内存分配由操作系统执行,在此不再赘述
(4) yarn.nodemanager.resource.memory-mb 可以分配给container的物理内存数量,默认8192M
(5) yarn.scheduler.increment-allocation-mb container内存增量,默认1024M
- MapReduce
(1) mapreduce.{map|reduce}.java.opts
(2) mapreduce.{map|reduce}.memory.mb
25.3 讲解
1. Yarn的ResourceManger(简称RM)通过逻辑上的队列分配内存,CPU等资源给application,默认情况下RM允许最大AM申请Container资源为8192MB(“yarn.scheduler.maximum-allocation-mb“),默认情况下的最小分配资源为1024M(“yarn.scheduler.minimum-allocation-mb“),如果参数中需要的资源在此范围之外,在任务submit的时候会被直接拒绝掉
2. AM只能以增量 ("yarn.scheduler.minimum-allocation-mb") + ("yarn.scheduler.increment-allocation-mb") 规整每个task需要的内存,并且申请的内存只能在(”yarn.scheduler.minimum-allocation-mb“)和(“yarn.scheduler.maximum-allocation-mb“) 的范围内向RM申请资源。用mr任务举例,再默认情况下,比如只修改了map task配置需要1536M内存,但实际分配出来map task占用2G内存,原因在于 container最小内存1024M < 1560M < container 最小内存为1024M + container内存增量1024M, 故分配2G内存。
25.4 图示
从上面的图可以看出map,reduce,AM container的JVM,“JVM”矩形代表服务进程,“Max heap”,“Max virtual”矩形代表NodeManager对JVM进程的最大内存和虚拟内存的限制。
以map container内存分配(“mapreduce.map.memory.mb“)设置为1536M为例,AM将会为container向RM请求2048mb的内存资源(原因见上)。这是一种逻辑上的分配,这个值被NodeManager用来监控改进程内存资源的使用率,如果Task进程树(包括task启动子进程占用的内存,这样可以解决hadoop streaming任务内存跑飞的情况,实际上是对内存使用的一种软限制,至于为什么没有使用Cgroups做限制,大家可以自行查阅资料)的使用超过了2048MB,NM将会把这个task给杀掉。
mapreduce.map.java.opts和mapreduce.map.memory.mb区别:JVM进程跑在container中,mapreduce.{map|reduce}.java.opts能够通过Xmx设置JVM最大的heap的使用,一般设置为0.75倍的mapreduce.{map|reduce}.memory.mb ,因为需要为java code,非JVM内存使用等预留些空间,同理:spark executor在申请内存是也会为堆外内存预留一些空间,参数由spark.yarn.executor.memoryOverhead 控制,算法为 max(384m, 0.07*spark.executor.memory) **
当一个mapreduce job完成时,你将会看到一系列的计数器被打印出来,下面的三个计数器展示了多少物理内存和虚拟内存被分配
Physical memory (bytes) snapshot=21850116096
Virtual memory (bytes) snapshot=40047247360
Total committed heap usage (bytes)=22630105088
25.5 虚拟内存
默认的(“yarn.nodemanager.vmem-pmem-ratio“)设置为2.1,意味则map container或者reduce container分配的虚拟内存超过2.1倍的(“mapreduce.reduce.memory.mb“)或(“mapreduce.map.memory.mb“)就会被NM给KILL掉,如果 (“mapreduce.map.memory.mb”) 被设置为1536M那么总的虚拟内存为2.1*1536=3225.6MB
当container的内存超出要求的,log将会打印信息:
Current usage: 2.1gb of 2.0gb physical memory used; 1.6gb of 3.15gb virtual memory used. Killing container.
25.6 内存调优
1、Mapper/Reducer阶段JVM内存溢出(一般都是堆)
1)JVM堆(Heap)内存溢出:堆内存不足时,一般会抛出如下异常:
第一种:“java.lang.OutOfMemoryError:” GC overhead limit exceeded;
第二种:“Error: Java heapspace”异常信息;
第三种:“running beyondphysical memory limits.Current usage: 4.3 GB of 4.3 GBphysical memoryused; 7.4 GB of 13.2 GB virtual memory used. Killing container”。
2) 栈内存溢出:抛出异常为:java.lang.StackOverflflowError
常会出现在SQL中(SQL语句中条件组合太多,被解析成为不断的递归调用),或MR代码中有递归调用。这种深度的递归调用在栈中方法调用链条太长导致的。出现这种错误一般说明程序写的有问题。
2、MRAppMaster内存不足
如果作业的输入的数据很大,导致产生了大量的Mapper和Reducer数量,致使MRAppMaster(当前作业的管理者)的压力很大,最终导致MRAppMaster内存不足,作业跑了一般出现了OOM信息
异常信息为:
Exception: java.lang.OutOfMemoryError thrown from theUncaughtExceptionHandler in thread
"Socket Reader #1 for port 30703
Halting due to Out Of Memory Error...
Halting due to Out Of Memory Error...
Halting due to Out Of Memory Error...
3、非JVM内存溢出
异常信息一般为:java.lang.OutOfMemoryError:Direct buffffer memory
自己申请使用操作系统的内存,没有控制好,出现了内存泄露,导致的内存溢出。错误解决参数调优
1、Mapper/Reducer阶段JVM堆内存溢出参数调优
目前MapReduce主要通过两个组参数去控制内存:(将如下参数调大)
Maper:
mapreduce.map.java.opts=-Xmx2048m(默认参数,表示jvm堆内存,注意是mapreduce不是mapred)
mapreduce.map.memory.mb=2304(container的内存)
Reducer:
mapreduce.reduce.java.opts=-=-Xmx2048m(默认参数,表示jvm堆内存)
mapreduce.reduce.memory.mb=2304(container的内存)
注意:因为在yarn container这种模式下,map/reduce task是运行在Container之中的,所以上面提到的mapreduce.map(reduce).memory.mb大小都大于mapreduce.map(reduce).java.opts值的大小。mapreduce.{map|reduce}.java.opts能够通过Xmx设置JVM最大的heap的使用,一般设置为0.75倍的memory.mb,因为需要为java code等预留些空间
2、MRAppMaster:
yarn.app.mapreduce.am.command-opts=-Xmx1024m(默认参数,表示jvm堆内存)
yarn.app.mapreduce.am.resource.mb=1536(container的内存)
注意在Hive ETL里面,按照如下方式设置:
set mapreduce.map.child.java.opts="-Xmx3072m"(注:-Xmx设置时一定要用引号,不加引号各种错误)
set mapreduce.map.memory.mb=3288
或
set mapreduce.reduce.child.java.opts="xxx"
set mapreduce.reduce.memory.mb=xxx
涉及YARN参数:
•yarn.scheduler.minimum-allocation-mb (最小分配单位1024M)
•yarn.scheduler.maximum-allocation-mb (8192M
•yarn.nodemanager.vmem-pmem-ratio (虚拟内存和物理内存之间的比率默认 2.1)
•yarn.nodemanager.resource.memory.mb
Yarn的ResourceManger(简称RM)通过逻辑上的队列分配内存,CPU等资源给application,默认情况下RM允许最大AM申请Container资源为8192MB(“yarn.scheduler.maximum-allocation-mb“),默认情况下的最小分配资源为1024M(“yarn.scheduler.minimum-allocation-mb“),AM只能以增量(”yarn.scheduler.minimum-allocation-mb“)和不会超过(“yarn.scheduler.maximum-allocationmb“)的值去向RM申请资源,AM负责将(“mapreduce.map.memory.mb“)和
(“mapreduce.reduce.memory.mb“)的值规整到能被(“yarn.scheduler.minimum-allocation-mb“)整除,RM会拒绝申请内存超过8192MB和不能被1024MB整除的资源请求。(不同配置会有不同)
25.7 mapred.child.java.opts
mapred.child.java.opts
这个参数是配置每个map或reduce使用的内存数量。默认的是200M。
mapred.child.java.opts就是设定jvm的参数之一,在新版本中已经标准为过期,取而代之的是区分Map Task 和Reduce Task 的jvm opts , mapred.map.child.java.opts和mapred.reduce.child.java.opts(默认值为-Xmx200m)
当用户在不设置该值情况下,会以最大1G jvm heap size启动task,有可能导致OutOfMemory,所以最简单的做法就是设大参数,并且由于这个值不是final,所以用户可以在自己的mapred-site.xml中可以覆盖默认值
其实在构造JVM Args的过程中,是有另外一个admin参考可以覆盖用户端设置的
mapreduce.admin.map.child.java.opts mapreduce.admin.reduce.child.java.opts
在mapred-site.xml中加上如下配置:
<property>
<name>mapreduce.admin.map.child.java.opts</name>
<value>-Xmx1024m</value>
</property>
<property>
<name>mapreduce.admin.reduce.child.java.opts</name>
<value>-Xmx5120m</value>
</property>
mapred.child.java.opts设置成多大比较合适:
这个参数是配置每个map或reduce使用的内存数量,默认是200m,一般情况下,该值设置为 总内存/并发数量(=核数)
mapred.map.child.java.opts和mapreduce.map.memeory.mb的区别:
mapreduce.map.memory.mb是向RM申请的内存资源大小,这些资源可用用于各种程序语言编写的程序, mapred.map.child.java.opts 一般只用于配置JVM参数
25.8 mapreduce优化
优化(1)资源相关参数:
以下参数是在自己的 MapReduce 应用程序中配置就可以生效
mapreduce.map.memory.mb: 一个 Map Task 可使用的内存上限(单位:MB),默认为 1024。如果 Map Task 实际使用的资源量超过该值,则会被强制杀死。
mapreduce.reduce.memory.mb: 一个 Reduce Task 可使用的资源上限(单位:MB),默认为 1024。如果 Reduce Task 实际使用的资源量超过该值,则会被强制杀死。
mapreduce.map.cpu.vcores: 每个 Maptask 可用的最多 cpu core 数目, 默认值: 1
mapreduce.reduce.cpu.vcores: 每个 Reducetask 可用最多 cpu core 数目默认值: 1
mapreduce.map.java.opts: Map Task 的 JVM 参数,你可以在此配置默认的 java heap size 等参数, 例如:“-Xmx1024m -verbose:gc -Xloggc:/tmp/@taskid@.gc”
(@taskid@会被 Hadoop 框架自动换为相应的 taskid), 默认值: “”
mapreduce.reduce.java.opts: Reduce Task 的 JVM 参数,你可以在此配置默认的 java heap size 等参数, 例如:“-Xmx1024m -verbose:gc -Xloggc:/tmp/@taskid@.gc”, 默认值: “”
以下在 yarn 启动之前就配置在服务器的配置文件中才能生效
yarn.scheduler.minimum-allocation-mb RM 中每个容器请求的最小配置,以 MB 为单位,默认 1024。
yarn.scheduler.maximum-allocation-mb RM 中每个容器请求的最大分配,以 MB 为单位,默认 8192。
yarn.scheduler.minimum-allocation-vcores 1
yarn.scheduler.maximum-allocation-vcores 32
yarn.nodemanager.resource.memory-mb 表示该节点上YARN可使用的物理内存总量,默认是 8192(MB),注意,如果你的节点内存资源不够 8GB,则需要调减小这个值,而 YARN不会智能的探测节点的物理内存总量。
shuffle 性能优化的关键参数,应在 yarn 启动之前就配置好
mapreduce.task.io.sort.mb 100 shuffle 的环形缓冲区大小,默认 100m
mapreduce.map.sort.spill.percent 0.8 环形缓冲区溢出的阈值,默认 80%
优化(2)容错相关参数:
mapreduce.map.maxattempts: 每个 Map Task 最大重试次数,一旦重试参数超过该值,则认为 Map Task 运行失败,默认值:4。
mapreduce.reduce.maxattempts: 每个Reduce Task最大重试次数,一旦重试参数超过该值,则认为 Map Task 运行失败,默认值:4。
mapreduce.map.failures.maxpercent: 当失败的 Map Task 失败比例超过该值,整个作业则失败,默认值为 0. 如果你的应用程序允许丢弃部分输入数据,则该该值设为一个大于 0 的值,比如 5,表示如果有低于 5%的 Map Task 失败(如果一个 Map Task 重试次数超过mapreduce.map.maxattempts,则认为这个 Map Task 失败,其对应的输入数据将不会产生任何结果),整个作业扔认为成功。
mapreduce.reduce.failures.maxpercent: 当失败的 Reduce Task 失败比例超过该值为,整个作业则失败,默认值为 0.
mapreduce.task.timeout:如果一个task在一定时间内没有任何进入,即不会读取新的数据,也没有输出数据,则认为该 task 处于 block 状态,可能是临时卡住,也许永远会卡住。为了防止因为用户程序永远 block 不退出,则强制设置了一个超时时间(单位毫秒),默认是600000,值为 0 将禁用超时。
优化(3)效率跟稳定性参数(任务的推测执行):
Straggle(掉队者)是指那些跑的很慢但最终会成功完成的任务。一个掉队的Map任务会阻止Reduce任务开始执行。
Hadoop不能自动纠正掉队任务,但是可以识别那些跑的比较慢的任务,然后它会产生另一个等效的任务作为备份,并使用首先完成的那个任务的结果,此时另外一个任务则会被要求停止执行。这种技术称为推测执行(speculative execution)。
默认使用推测执行。
属性 描述
mapreduce.map.speculative 控制Map任务的推测执行(默认true)
mapreduce.reduce.speculative 控制Reduce任务的推测执行(默认true)
mapreduce.job.speculative.speculativecap 推测执行功能的任务能够占总任务数量的比例(默认0.1,范围0~1)
mapreduce.job.speculative.slownodethreshold 判断某个TaskTracker是否适合启动某个task的speculative task(默认1)
mapreduce.job.speculative.slowtaskthreshold 判断某个task是否可以启动speculative task(默认1)
mapreduce.input.fileinputformat.split.minsize FileInputFormat做切片时最小切片大小,默认 1。
mapreduce.input.fileinputformat.split.maxsize FileInputFormat做切片时最大切片大小