我在Spark的笛卡尔函数中遇到了不良结果。小数据集无法重现;它只会持续存在大型数据集。
例如:
小数据集
a = sc.parallelize([1, 2, 3, 4, 5])
b = sc.parallelize([(100, 150), (200, 250), (300, 350), (400, 450), (500, 550)])
c = a.cartesian(b)
print c.collect()
print c.count()
print c.collect()
[(1,(100,150)),(1,(200,250)),(2,(100,150)),(2,(200,250)),(1,(300, 350)),(1,(400,450)),(2,(300,350)),(2,(400,450)),(1,(500,550)),(2,(500, 550)),(3,(100,150)),(3,(200,250)),(4,(100,150)),(4,(200,250)),(5,(100, 150)),(5,(200,250)),(3,(300,350)),(3,(400,450)),(4,(300,350)),(4,(400, 450)),(3,(500,550)),(4,(500,550)),(5,(300,350)),(5,(400,450)),(5,(500, 550))]
print c.count()
25
由于“a”有5个元素而“b”有5个元素,因此两者的笛卡尔积是25个元素。但是,对于大型数据集,笛卡尔的大小小于预期值。
大型数据集
x = sc.parallelize([1, 2, 3, 4, 5])
print x.collect()
"""
y is a RDD in the same format as b.
y.count() == 19475211
"""
print y.take(5)
z = x.cartesian(y)
print z.take(5)
print z.count()
print x.collect()
[(1,2,3,4,5)]
print y.take(5)
[(5120,2560),(5120,408),(5120,520),(5120,3500),(5120,2060)]
print z.take(5)
[(1,(5120,2560)),(1,(5120,408)),(1,(5120,520)),(5120,(3500,1)),(5120,(2060, 1))]
print z.count()
7451200
如果您注意到大数据集,当您采用x和y的笛卡儿时,z的第4个元素是(5120,(3500,1))而不是(1,(5120,3500))。 z的第五个元素是(5120,(2060,1))而不是(1,(5120,2060))。
此外,z的大小为7451200而不是19475211 * 5 = 97376055.
导致此问题的原因是什么?什么是防止这种情况发生的解决方案?
答案 0 :(得分:0)
虽然我还没弄清楚为什么会这样,但我确实解决了这个问题。我首先播放x列表然后在y上执行平面地图操作。结果z是我期望的结果。
x = sc.broadcast([1, 2, 3, 4, 5])
z = y.flatMap(lambda (y_1, y_2): [(x_elt, (y_1, y_2)) for x_elt in x.value])