我在21个执行程序的独立模式下运行spark,当我使用我的sqlContext加载我的第一个SQL表时,我对它进行分区,使得数据在所有块之间通过分区在一个列上完美地分配顺序整数:
val brDF = sqlContext.load("jdbc", Map("url" -> srcurl, "dbtable" -> "basereading", "partitionColumn" -> "timeperiod", "lowerBound" ->"2", "upperBound" -> "35037", "numPartitions" -> "100"))
此外,这些块很好地分布在每个群集上,因此每个群集都具有类似的内存使用量。 不幸的是,当我加入一个更小的表idoM时,就像这样:
val mrDF = idoM.as('idom).join(brS1DF.as('br), $"idom.idoid" === $"br.meter")
当idoM是1列表并缓存结果时,RDD块存储在集群上的方式的分布发生了变化:
screenshot of spark UI executors sorted by number of RDD blocks
现在,我的第四个集群上突然出现了更多RDD块,它使用了更多内存。在检查每个RDD时,它们的块似乎仍然很好地分布,所以我的分区仍然很好,只是所有块似乎只想写在一个簇上,从而打破了多个开始的目的。
我怀疑我的问题有类似的问题 this question on the Apache mail list 但没有答案,所以任何事情都会受到高度赞赏。
答案 0 :(得分:1)
不知道您的数据,我认为您加入的密钥的分布是导致数据偏差的原因。
正在运行idoM.groupBy("idoid").count.orderBy(desc("count")).show
或brS1DF.groupBy("meter").count.orderBy(desc("count")).show
可能会向您显示一些值有很多值。
答案 1 :(得分:0)
问题在于idoM被加载到一台机器上,并且火花试图保持数据局部性并在一台机器上进行整个连接,在这种情况下通过将较小的表广播到较大的一台来解决。我确保idoM的键完全分布在正在连接的列上,不幸的是,重新分区并没有解决问题,因为spark仍然试图保持局部性并且整个dataFrame仍然在一台机器上结束。