Spark的几种去重的原理分析

前言

我们经常做去重的操作,事实上几种方式可以实现去重,但是结果的理解其实是不一样的,不过在一定程度上这几种也都可以满足我们的需求。

参考数据

idname
1a
2b
1a
1b

Distinct去重

这个其实是真正的去重,语意上其实就是如果出现一样的结果,则就显示一行
可以作用单行或者多行

select distinct id from t;
id
1
2

或者是
select distinct id,name from t;
作用多行的时候多行要一起相等才行

idname
1a
2b
1b

group by操作

实际上这个要求去重列作为聚合字段,我们一般可以做聚合去实现

select count(*) as cnt,id,name from t group by id,name;

当我们不关心聚合结果的时候得到的结果就是去重的结果了

row_number开窗操作

实际上我们要分开来看,首先是开窗之后的结果

select row_number() over (partition by id)  as rn ,id,name  from t
rnidname
11a
21b
31b
12b

这个操作会把相同的id增加一个序号列,我们一般是外面套一个过滤条件去筛选

select * from (
select row_number() over (partition by id)  as rn ,id,name  from t
) h where h.rn=1; 

这种做法实际上是在所有记录中取一条记录。

性能分析

事实上直接的distinct的话直接做一次reduceByKey就可以了,简单来说,这个在map端是可以优化
在这里插入图片描述
当然优化都是建立在数据量大的时候才有意义,当数据输出比较大的时候,map端可以多做一步
在这里插入图片描述
同样的道理,我们做group by其实也可以这样子做,这个技术其实是combine技术,减少网络传输

关键的前提是允许这么干才行,否则是拿不到要的结果的,row_number()的操作类似这样子的,需要提前编号,再进行过滤

在这里插入图片描述
从图中就可以发现,中间过程的要求,导致我们不能做一个map操作的优化,所以其实是会慢一些,但是row_number实际上会保留我们需要的那行数据本身,所以大部分情况是不能被group by替代的

总结

其实几种去重的方式本质上意义是不一样的,这也是满足不同的需求下的操作,表面上差不多,实际考虑实现的时候还是要多琢磨一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值