目录
reduce join
map join
总结
本篇文章记录用户访问session分析-数据倾斜解决方案之将reduce join转换为map join
reduce join
普通的join,那么肯定是要走shuffle;那么,所以既然是走shuffle,那么普通的join,就肯定是走的是reduce join。 先将所有相同的key,对应的values,汇聚到一个task中,然后再进行join。
map 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比较小的情况下。
reduce join转换为map join,不适合的情况
两个RDD都比较大,那么这个时候,你去将其中一个RDD做成broadcast,就很笨拙了。很可能导致内存不足。最终导致内存溢出,程序挂掉。 而且其中某些key(或者是某个key),还发生了数据倾斜;此时可以采用最后两种方式。
总结
对于join这种操作,不光是考虑数据倾斜的问题;即使是没有数据倾斜问题,也完全可以优先考虑,用我们讲的这种高级的reduce join转map join的技术,不要用普通的join,去通过shuffle,进行数据的join;完全可以通过简单的map,使用map join的方式,牺牲一点内存资源;在可行的情况下,优先这么使用。 不走shuffle,直接走map,是不是性能也会高很多?这是肯定的。
/**
* 这里就可以说一下,比较适合采用reduce join转换为map join的方式
*
* userid2PartAggrInfoRDD,可能数据量还是比较大,比如,可能在1千万数据
* userid2InfoRDD,可能数据量还是比较小的,你的用户数量才10万用户
*
*/
/**
* reduce join转换为map join
*/
// List<Tuple2<Long, Row>> userInfos = userid2InfoRDD.collect();
// final Broadcast<List<Tuple2<Long, Row>>> userInfosBroadcast = sc.broadcast(userInfos);
//
// JavaPairRDD<String, String> sessionid2FullAggrInfoRDD = userid2PartAggrInfoRDD.mapToPair(
//
// new PairFunction<Tuple2<Long,String>, String, String>() {
//
// private static final long serialVersionUID = 1L;
//
// @Override
// public Tuple2<String, String> call(Tuple2<Long, String> tuple)
// throws Exception {
// // 得到用户信息map
// 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);
// }
//
// });