(四十六)数据倾斜解决方案之将reduce join转换为map join

在这里插入图片描述
普通的join,那么肯定是要走shuffle;那么,所以既然是走shuffle,那么普通的join,就肯定是走的是reduce join
先将所有相同的key,对应的values,汇聚到一个task中,然后再进行join。

reduce join转换为map join,适合在什么样的情况下,可以来使用

  • 如果两个RDD要进行join,其中一个RDD是比较小的。一个RDD是100万数据,一个RDD是1万数据。(一个RDD是1亿数据,一个RDD是100万数据)
  • 其中一个RDD必须是比较小的,broadcast出去那个小RDD的数据以后,就会在每个executor的block manager中都驻留一份。要确保你的内存足够存放那个小RDD中的数据
    这种方式下,根本不会发生shuffle操作,肯定也不会发生数据倾斜;从根本上杜绝了join操作可能导致的数据倾斜的问题;
    对于join中有数据倾斜的情况,大家尽量第一时间先考虑这种方式,效果非常好;前提是某个RDD比较小的情况下。

不适合的情况

两个RDD都比较大,那么这个时候,你去将其中一个RDD做成broadcast,就很笨拙了。很可能导致内存不足。最终导致内存溢出,程序挂掉。
而且其中某些key(或者是某个key),还发生了数据倾斜;此时可以采用最后两种方式。

对于join这种操作,不光是考虑数据倾斜的问题;即使是没有数据倾斜问题,也完全可以优先考虑,用我们讲的这种高级的reduce join转map join的技术,不要用普通的join,去通过shuffle,进行数据的join;完全可以通过简单的map,使用map join的方式,牺牲一点内存资源;在可行的情况下,优先这么使用。

不走shuffle,直接走map,是不是性能也会高很多?这是肯定的。

   /*
   userid2partAggrInfoRDD的数据量可能是比较大的 比如1000万条数据
   而userid2InfoRDD是一用户表 数据量可能是比较小的
   可以将它改成map join
    */
        JavaPairRDD<Long,Tuple2<String,Row>> userid2FullInfoRDD=userid2PartAggrInfoRDD.join(userid2InfoRDD);
        JavaPairRDD<String,String> sesionid2FullAggrInfoRDD=userid2FullInfoRDD.mapToPair(
                new PairFunction<Tuple2<Long, Tuple2<String, Row>>, String, String>() {
                    @Override
                    public Tuple2<String, String> call(Tuple2<Long, Tuple2<String, Row>> tuple) throws Exception {
                        String partAggrInfo=tuple._2._1;
                        Row userInfoRow=tuple._2._2;
                        String sessionid=StringUtils.getFieldFromConcatString(partAggrInfo,"\\|",Constants.FIELD_SESSION_ID);
                        int age=userInfoRow.getInt(3);
                        String professional=userInfoRow.getString(4);
                        String city=userInfoRow.getString(5);
                        String sex=userInfoRow.getString(6);
                        String fullAggrInfo=partAggrInfo+"|"
                                +Constants.FIELD_AGE+"="+age+"|"
                                +Constants.FIELD_PROFESSIONAL+"="+professional+"|"
                                +Constants.FIELD_CITY+"="+city+"|"
                                +Constants.FIELD_SEX+"="+sex;
                        return new Tuple2<String, String>(sessionid,fullAggrInfo);
                    }
                }
        );
        List<Tuple2<Long,Row>> userInfos=userid2InfoRDD.collect();
        final Broadcast<List<Tuple2<Long,Row>>> userInfosBroadcast=sc.broadcast(userInfos);
        JavaPairRDD<String,String> tunedRDD=userid2PartAggrInfoRDD.mapToPair(new PairFunction<Tuple2<Long, String>, String, String>() {
            @Override
            public Tuple2<String, String> call(Tuple2<Long, String> tuple) throws Exception {
                List<Tuple2<Long,Row>> userInfos=userInfosBroadcast.value();
                Map<Long,Row> userInfoMap=new HashMap<Long, Row>();
                for(Tuple2<Long,Row> userInfo:userInfos){
                    userInfoMap.put(userInfo._1,userInfo._2);
                }
                String partAggrInfo=tuple._2;
                Row userInfoRow=userInfoMap.get(tuple._1);
                String sessionid=StringUtils.getFieldFromConcatString(partAggrInfo,"\\|",Constants.FIELD_SESSION_ID);
                int age=userInfoRow.getInt(3);
                String professional=userInfoRow.getString(4);
                String city=userInfoRow.getString(5);
                String sex=userInfoRow.getString(6);
                String fullAggrInfo=partAggrInfo+"|"
                        +Constants.FIELD_AGE+"="+age+"|"
                        +Constants.FIELD_PROFESSIONAL+"="+professional+"|"
                        +Constants.FIELD_CITY+"="+city+"|"
                        +Constants.FIELD_SEX+"="+sex;
                return new Tuple2<String, String>(sessionid,fullAggrInfo);
            }
        });

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值