hive中常用的几个排序
order by #全局排序,因为是全局排序,所以job是一个reduce,reduce的个数参数设置对其无效
sort by #一个reduce时为全局排序,多个reduce时,每个reduce各自排序,为了提高全局排序的性能,可以先用sort by做局部排序,然后再做全局排序
distribute by #hash 分组,根据key和reduce个数进行数据分发,默认使用hash的方式
cluster by #distribute by + sort by(注意和hive.enforce.bucketing参数的应用)
结合两个例子来看排序的应用:
1)cdnjob的优化思路
熟悉map slot的分配规则的同学应该知道,text gz的文件是不支持split的,因此这种情况下最多只有一个map(不管数据量多大),
这样在做数据处理时,如果文件很大而且计算逻辑比较复杂(比如cdn的报表,需要做各种聚合计算和ip地址的解析),效率就会比较低下。
一个思路就是建一个中间表,对原始表进行distribute by,对中间表进行复杂的计算,这样就可以使用多个map,提高运算效率。
2)solr测试的思路
测试hive2solr时,需要模拟一个文件和多个文件的写入情况。
默认使用的sql是
1
|
insert into table xxx
select
* from data_for_sol;
|
这是一个hdfs操作,不涉及mapred,不太好模拟多个文件的写入情况。
可以在后面套一个 distribute by ,并合理设置reduce的数量(mapred.reduce.tasks),这样就会生成多个reduce的文件。
1
|
insert into table xxx
select
* from data_for_solr distribute by session_id;
|
注意:reduce slot的分配由下面几个情况决定
1)sql类型(比如order by只有一个reduce)
2)参数
1
|
mapred.reduce.tasks;
|
每个任务reduce的默认值,默认为-1,-1 代表自动根据作业的情况来设置reduce的值,优先级高于下面两个设置。
1
|
hive.
exec
.reducers.bytes.per.reducer
|
根据reduce的输入数据(map端的输出数据,不管是否压缩),大小判断reduce的个数,默认1G
hive.exec.reducers.max reduce的最大数量,默认999个
计算方法:
1
2
3
4
5
|
reducers = (int) ((totalInputFileSize + bytesPerReducer - 1) / bytesPerReducer);
reducers = Math.max(1, reducers);
reducers = Math.min(maxReducers, reducers);
关于map
/reduce
slot的分配规则以后有机会再说。
|