我有一个数据集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中的分区数据中读取数据。我尝试的每一种方式,我仍然得到一个洗牌。我做错了什么?
答案 0 :(得分:0)
我通过使用mapPartitions函数并将其传递给我自己的reduce函数来解决我的问题,以便它在每个节点上本地“减少”并且永远不会执行随机播放。
在每个分区之间隔离数据的情况下,它完美地运行。当多个分区上存在相同的密钥时,这是需要随机播放的地方,但这种情况需要单独检测和处理。