有没有办法提高PySpark输出的效率?

时间:2017-12-01 18:30:09

标签: performance scala apache-spark pyspark pyspark-sql

我正在尝试测试PySpark迭代一些非常大(10s的GB到1s的TB)数据的能力。对于大多数脚本,我发现PySpark具有与Scala代码大致相同的效率。在其他情况下(如下面的代码),我会遇到严重的速度问题,速度从10到12倍不等。

path = "path/to/file"
spark = SparkSession.builder.appName("siteLinkStructureByDate").getOrCreate()
sc = spark.sparkContext   

df = RecordLoader.loadSomethingAsDF(path, sc, spark)
fdf = df.select(df['aDate'], df['aSourceUrl'], df['contentTextWithUrls'])
rdd = fdf.rdd
rddx = rdd.map (lambda r: (r.aDate, CreateAVertexFromSourceUrlAndContent(r.aSourceUrl, r.contentTextWithUrls)))\
 .flatMap(lambda r: map(lambda f: (r[0], ExtractDomain(f[0]), ExtractDomain(f[1])), r[1]))\
 .filter(lambda r: r[-1] != None)\
 .countByValue()

print([((x[0], x[1], x[2]), y) for x, y in rddx.items()]) 

我们认为我们已将问题隔离到.countByValue()(返回defaultdict),但应用countItems()或reduceByKey()会产生几乎相同的结果。我们也99%确定问题不在于ExtractDomain或CreateAVertexFromSourceUrlAndContent(不是函数的真实名称,只是伪代码使其易于理解)。

所以我的问题首先是

  1. 这段代码中有什么可以减少时间吗?
  2. PySpark基本上 比它的Scala慢得多 对方?
  3. 有没有办法复制flatmap 改为使用PySpark数据帧(理解数据帧是 一般比Pyspark的RDD快?)

1 个答案:

答案 0 :(得分:2)

这里最大的问题可能是通信 - Spark SQL(列式格式) - >普通的Scala对象 - >泡菜(Pyrolite) - >插座 - > unpickle - >普通的Python对象。这是很多复制,转换和移动的东西。

  

有一种方法可以使用PySpark数据帧复制flatmap而不是

是。它被称为explode - 但公平地说它也很慢。

  

了解数据帧通常比Pyspark中的RDD更快

这通常是正确的(Scala和Python都是),但您可能需要udf来实现ExtractDomainCreateAVertexFromSourceUrlAndContent - 这是另一个缓慢的事情。只需使用您可以使用的名称parse_url_tuple

  

PySpark基本上比Scala对手慢得多吗?

有点慢。通常情况下,调优良好的代码不会那么慢。但实现细节是不同的 - Scala和Python中的相同操作集可以以不同的方式实现。

  

这段代码中有什么我可以做的来减少时间吗?

我建议先进行分析。一旦确定哪个部分负责(转换,合并),您就可以尝试定位它。