Hive去重方法简记

Distinct用法

(1)当distinct应用到多个字段的时候,distinct必须放在开头,其应用的范围是其后面的所有字段,而不只是紧挨着它的一个字段,而且distinct只能放到所有字段的前面。

(2)distinctNULL是不进行过滤的,即返回的结果中是包含NULL值的。

(3)聚合函数中的DISTINCT,如 COUNT( DISTINCT A)过滤掉为NULL 的项。

1
2
select distinct id,age from tmp.tmp01
select count(distinct id)as num from tmp.tmp01

注意:统计函数一般和group by搭配使用。

group by用法

对group by 后面所有字段去重,并不只是对一列去重。

示例一

1
2
3
4
5
6
select a.id
from (select distinct id,age
from tmp.tmp01
order by age desc
) a
group by a.id

**注意,**对id去重时可以用group by 或者distinct id,两者去重后的id排序时一致的,但是加了distinct(group by)后,distinct字段自带排序功能,会先按照distinct后面的字段进行排序,即已经改变了子查询中order by的排序,但是结果与正确结果中的id是一样的,只是排序不同罢了,以上这种写法是不优雅的,所以是不推荐的。

示例二

1
2
3
4
5
6
select a.id
from (select id,max(age) as age
from tmp.tmp01
group by id
order by age desc
) a

ROW_Number() over()窗口函数

注意:ROW_Number() over (partition by id order by number DESC) 给每个id加一列按number 倒叙的rank值,取rank=1

1
2
3
4
5
6
select m.id,m.age,m.number,m.rank
from (select id,age,number,ROW_Number() over(partition by id order by number) rank
from tmp.tmp01
where id!='' and number!='' or age!=''
) m
where m.rank=1

示例三

1
2
3
4
5
6
7
select n.id
from (select m.id,m.age
from (select id,age,ROW_Number() over(partition by id order by id) rank
from tmp.tmp01
) m
where m.rank=1
)n

去重性能

使用distinct会将所有的id都shuffle到一个 reduce里面,这就是我们所说的数据倾斜,都倾斜到一个reduce ,速度当然会慢。

由于没有手动指定reduce的个数,Hive会根据数据的大小动态的指定reduce大小,你也可以手动指定

hive> set mapred.reduce.tasks=100,所以如果数据量特别大的情况下,尽量不要使用distinct。

具体使用来说得看具体情况,直接使用distinct可读性好,数据量如果不大的话推荐使用,如果数据太大了,性能受到影响了,能使用group by代替distinct 就不要使用distinct 。

ROW_Number() over()窗口函数本身是排序用的函数,功能上可以实现去重,但是不推荐去重使用。