使用数据帧进行循环更快pyspark

时间:2020-05-09 17:47:14

标签: pyspark apache-spark-sql pyspark-dataframes

我需要遍历元素的数据框-更确切地说是顶点,但这并不重要-使用以下标头[vertexId, userName, communityId]-这里的communityId只是给定顶点的标签,执行许多每个步骤在当前行上进行数据框操作:

verticesIdsList = [row['id'] for row in vertices.select('id').collect()]

for vertexId in verticesIds:

    allCommunitiesDf = vertices.select('communityId').distinct()
    vertices2CommunitiesDf = verticesHelper.select('id', 'communityId')
    verticesIdsDf = verticesHelper.select('id')

    kInnerDf = vertices2CommunitiesDf \
                .join(aij, [aij.dst == vertices2CommunitiesDf.id]) \
                .where(aij.src == vertexId) \
                .groupBy('src', 'communityId').sum('weight')

   # compute some other params similiar to kInnerDf
   # change the communityId label for the current vertex according to a formula 
   # based on the above computed params
   # take into account THAT kInnerDF AND THE OTHER PARAMS NEED TO KNOW THE UPDATED LABELS FOR EACH VERTEX

尽管数据集最多包含500个元素(因此非常小),但我没有使用udfs-只是普通的数据帧-过程非常缓慢-耗时超过15分钟。 它的表现比非并行差!

当我删除for循环并改用udf时-一切都在几秒钟内完成。 为什么不使用udf方法?因为我需要根据所有顶点的社区ID标签重新计算参数,并且社区ID标签会随着每个顶点的处理而变化。

这是产生最佳结果的配置(由于数据集很小,我发现我需要更少的资源来避免开销):

customConfig = pyspark.SparkConf() \
.setAll([('spark.executor.memory', '2g'), \
    ('spark.sql.shuffle.partitions', '1'), \
    ('spark.default.parallelism', '1'), \
    ('spark.executor.cores', '1'), \
    ('spark.cores.max', '1'), \
    ('spark.driver.memory','50g'), \
    ('spark.sql.crossJoin.enabled', True)])

如何使此代码运行更快?为什么这么慢?

0 个答案:

没有答案