通过预分区文件避免Spark中的混乱(PySpark)

时间:2018-03-08 20:09:12

标签: apache-spark pyspark rdd pyspark-sql

我有一个数据集dataset,它在值00-99上分区,并且想要创建一个RDD first_rdd来读取数据。

然后我想算一下这个词多少次" foo"发生在每个分区的第二个元素中,并将每个分区的记录存储在列表中。我的输出为final_rdd,其中每条记录的格式为(partition_key, (count, record_list))

def to_list(a):
    return [a]

def append(a, b):
    a.append(b)
    return a

def extend(a, b):
    a.extend(b)
    return a

first_rdd = sqlContext.sql("select * from dataset").rdd
kv_rdd = first_rdd.map(lambda x: (x[4], x)) # x[4] is the partition value
# Group each partition to (partition_key, [list_of_records])
grouped_rdd = kv_rdd.combineByKey(to_list, append, extend)

def count_foo(x):
    count = 0
    for record in x:
        if record[1] == "foo":
            count = count + 1
    return (count, x)

final_rdd = grouped_rdd.mapValues(count_foo)
print("Counted 'foo' for %s partitions" % (final_rdd.count))

由于数据集的每个分区在计算上彼此完全独立,因此Spark不需要随机播放,但是当我查看SparkUI时,我注意到combineByKey导致了非常大的混乱。

我有正确数量的初始分区,并且还尝试从HDFS中的分区数据中读取数据。我尝试的每一种方式,我仍然得到一个洗牌。我做错了什么?

1 个答案:

答案 0 :(得分:0)

我通过使用mapPartitions函数并将其传递给我自己的reduce函数来解决我的问题,以便它在每个节点上本地“减少”并且永远不会执行随机播放。

在每个分区之间隔离数据的情况下,它完美地运行。当多个分区上存在相同的密钥时,这是需要随机播放的地方,但这种情况需要单独检测和处理。