标签:
杂谈 |
分类: 学习生涯 |
由于row_number()每行都需要返回一个行号值,所以一般的思路是通过实现最简单udf,继承org.apache.hadoop.hive.ql.exec.UDF即可。
昨天读了下row_number()的实现函数,和大家共享下。代码并不长,所以直接贴出
packagecom.alibaba.hive.udf.UDFRow_number;
importorg.apache.hadoop.hive.ql.exec.UDF;
public classRow_number extends UDF
{
private static String comparedColumn[] =
newString[MAX_VALUE];
private static int rowNum = 1;
}
通过static静态变量rowNum来控制行号的生成,的确是个好主意,那么如果想用这个函数来实现类似序列号生成器似乎也是一个好主意。
比如这么写
select ROW_NUMBER(1) rn, keyword from
idl_ae_kw_search_fdt0 wherehp_stat_date='2012-05-29'
limit 10;
我心中想,列rn的值永远是1,那么这个计数器永远++,rn肯定返回相应的序号。
最初的结果似乎验证了我的想法,
结果如下:
1
2
3
4
5
6
7
8
9
10
Perfect!
但是我这么写,结果就不对了,
create table xxxx asselect row_number(1) rn,keyword from (select
keyword from
idl_ae_kw_search_fdt0a where hp_stat_date='2012-05-29') a;
-- 306601Rows loaded tohdfs://hdpnn:9000/group/alibaba-dw-icbu/tmp/hive-dwapp/hive_2012-06-02_16-55-34_552_3638084487215847155/-ext-10000
有306601条数据,按我的想法,最大的rn应该是306601才是对的,
select max(rn) from xxxx;
结果才153362,震惊啊!这究竟是怎么一回事,
我再写了这么一条sql,
select * from xxxx awhere a.rn=1;
结果如下:
1
1
计数器生成了两个1,这究竟是怎么一回事??明明列值都是相等的,rownum参数怎么可能变强制回归1呢?
我发现到这么一个事情,hive告诉我,任务被拆成了两个map,一个reduce执行,那么合理的解释只能是这样,在以上语句里,row_number()
我们在来验证是否的确如此,我强制将map个数设置为4个(set mapred.map.tasks=4;),再跑下上面的语句,结果如下:
select max(rn) from xxxx;
82988
select * from xxxx awhere a.rn=1;
1
1
1
1
以上的结果验证了row_number()
最初的想法是:可以直接设置map个数为1吗?
如果直接在代码里显性设置set
mapred.map.tasks=1;
答案:不一定行。因为如果原表本身的文件个数是两个,那么无论你怎么设置map个数,hive还是会至少生成两个map,hive会操作多个input文件,所以hive默认会把map的任务数设置成输入的文件数目,即使你通过set设置了数目,也不起作用。
答案只有一个:设置reduce格式为1,在reduce处跑这个udf
1.
Yes
2.
Yes
上面两句都可以获得不重复的rownum,
那么下面这条语句肯定行不行呢?
create table smxxx as select row_number(1)rownum,a.keyword from
(select keyword from
idl_ae_kw_search_fdt0 a wherehp_stat_date='2012-05-29') a;
回答是:NO
为啥呢?你能告诉我吗?