合理设置
Map
及
Reduce
数
1
)
通常情况下,作业会通过
input
的目录产生一个或者多个
map
任务。
主要的决定因素有:
input
的文件总个数,
input
的文件大小,集群设置的文件块大小。
2
)
是不是
map
数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小
128m
),则每个小文件
也会被当做一个块,用一个
map
任务来完成,而一个
map
任务启动和初始化的时间远远大
于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的
map
数是受限的。
3
)
是不是保证每个
map
处理接近
128m
的文件块,就高枕无忧了?
答案也是不一定。比如有一个
127m
的文件,正常会用一个
map
去完成,但这个文件只
有一个或者两个小字段,却有几千万的记录,如果
map
处理的逻辑比较复杂,用一个
map
任务去做,肯定也比较耗时。
针对上面的问题
2
和
3
,我们需要采取两种方式来解决:即减少
map
数和增加
map
数;
5.1
复杂文件增加
Map
数
当
input
的文件都很大,任务逻辑复杂,
map
执行非常慢的时候,可以考虑增加
Map
数,
来使得每个
map
处理的数据量减少,从而提高任务的执行效率。
增加
map
的方法为:根据
computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
公式,
调整
maxSize
最大值。让
maxSize
最大值低于
blocksize
就可以增加
map
的个数。
案例实操:
1
)执行查询
2)设置最大切片值为 100 个字节
5.2 小文件进行合并
1
)
在
map
执行前合并小文件,减少
map
数:
CombineHiveInputFormat
具有对小文件进行合
并的功能(系统默认的格式)。
HiveInputFormat
没有对小文件合并功能。
set hive.input.format=
org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
2
)
在
Map-Reduce
的任务结束时合并小文件的设置:
在
map-only
任务结束时合并小文件,默认
true
SET hive.merge.mapfiles = true;
在
map-reduce
任务结束时合并小文件,默认
false
SET hive.merge.mapredfiles = true;
合并文件的大小,默认
256M
SET hive.merge.size.per.task = 268435456;
当输出文件的平均大小小于该值时,启动一个独立的
map-reduce
任务进行文件
merge
SET hive.merge.smallfiles.avgsize = 16777216;
5.3
合理设置
Reduce
数
1
)调整
reduce
个数方法一
(1)每个
Reduce
处理的数据量默认是
256MB
hive.exec.reducers.bytes.per.reducer=256000000
(2)每个任务最大的
reduce
数,默认为
1009
hive.exec.reducers.max=1009
(3)计算
reducer
数的公式
N=min(
参数
2
,总输入数据量
/
参数
1)
2
)调整
reduce
个数方法二
在
hadoop
的
mapred-default.xml
文件中修改
设置每个
job
的
Reduce
个数
set mapreduce.job.reduces = 15;
3
)
reduce
个数并不是越多越好
(1)过多的启动和初始化
reduce
也会消耗时间和资源;
(2)另外,有多少个
reduce
,就会有多少个输出文件,如果生成了很多个小文件,那
么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置
reduce
个数的时候也需要考虑这两个原则:处理大数据量利用合适的
reduce
数;
使单个
reduce
任务处理数据量大小要合适;
并行执行
Hive
会将一个查询转化成一个或者多个阶段。这样的阶段可以是
MapReduce
阶段、抽
样阶段、合并阶段、
limit
阶段。或者
Hive
执行过程中可能需要的其他阶段。默认情况下,
Hive
一次只会执行一个阶段。不过,某个特定的
job
可能包含众多的阶段,而这些阶段可能
并非完全互相依赖的,也就是说有些阶段是可以并行执行的,这样可能使得整个
job
的执行
时间缩短。不过,如果有更多的阶段可以并行执行,那么
job
可能就越快完成。
通过设置参数
hive.exec.parallel
值为
true
,就可以开启并发执行。不过,在共享集群中,
需要注意下,如果
job
中并行阶段增多,那么集群利用率就会增加。
set hive.exec.parallel=true; //
打开任务并行执行
set hive.exec.parallel.thread.number=16; //
同一个
sql
允许最大并行度,默认为
8
。
当然,得是在系统资源比较空闲的时候才有优势,否则,没资源,并行也起不来。
7
严格模式
Hive
可以通过设置防止一些危险操作:
1
)分区表不使用分区过滤
将
hive.strict.checks.no.partition.filter
设置为
true
时,对于分区表,
除非
where
语句中含
有分区字段过滤条件来限制范围,否则不允许执行。
换句话说,就是用户不允许扫描所有分
区。进行这个限制的原因是,通常分区表都拥有非常大的数据集,而且数据增加迅速。没有
进行分区限制的查询可能会消耗令人不可接受的巨大资源来处理这个表。
2
)使用
order by
没有
limit
过滤
将
hive.strict.checks.orderby.no.limit
设置为
true
时,对于
使用了
order by
语句的查询,要
求必须使用
limit
语句。
因为
order by
为了执行排序过程会将所有的结果数据分发到同一个
Reducer
中进行处理,强制要求用户增加这个
LIMIT
语句可以防止
Reducer
额外执行很长一
段时间。
3
)笛卡尔积
将
hive.strict.checks.cartesian.product
设置为
true
时,
会限制笛卡尔积的查询。
对关系型数
据库非常了解的用户可能期望在 执行
JOIN
查询的时候不使用
ON
语句而是使用
where
语
句,这样关系数据库的执行优化器就可以高效地将
WHERE
语句转化成那个
ON
语句。不幸
的是,
Hive
并不会执行这种优化,因此,如果表足够大,那么这个查询就会出现不可控的情
况。
10.8 JVM
重用