原文链接:https://www.jianshu.com/p/5e593510313b
大纲
问题描述
解决方案
代码以及效果
总结
1.问题描述
要做的事情
从一堆房源hive表和hdfs数据中读取信息,并将同一id的信息整合到一起。共有5个hive表,2个hdfs文件;每个表所需操作的id数是千万数量级,每个表中字段20~200不等。
当前做法
用pyspark读取hive表以及hdfs的数据,并转换成rdd,然后用leftOuterJoin将信息整合;这样做需消耗至少30min,甚至1h的时间,速度太慢。本文就是针对该问题进行的优化。
2.解决方案
错误尝试
对于程序的性能问题,其实最开始的做法应该是打印每个步骤所需的时间,然后从最耗费时间的步骤开始。
但是我最开始并没有这样做,因为leftOuterJoin的操作是, 为表的大小,因此我以为leftOuterJoin是最耗时的。于是我直接将leftOuterJoin换成了rdd.union(), 然后再reduceByKey的方式。但是当我将所有的leftOuterJoin操作改过来后,发现总的时间还是需要30min。
另外提醒下,当数据量过大时,用leftOuterJoin容易出现内存溢出的问题;当两个rdd数量级差别较大时,用reduceByKey容易出现数据倾斜的问题。如果是两个rdd取交集的话,建议先用filter过滤,然后再用reduceByKey进行合并操作。
找对方向
hive数据直接用dataframe操作
说实话,看到这个效果有点沮丧。不过,我在等待程序运行的过程中,发现将两个rdd用reduceByKey操作的时间并不长,大量的时间其实花在读取hive表并转成rdd的阶段。这时我才意识到,我应该打印出每步操作的时间,针对性地优化。很快,验证了我的想法,确实在转换rdd耗费了不少时间。
转换成rdd是为了做两张表合并的操作,然后我查资料发现,其实针对结构化的数据,dataframe和dataset比rdd处理更快;而数据从hive表中读出后本身就是dataframe的格式,其实完全没有必要转成rdd。实验后,果然省下不少时间。另外,用dataframe的j