我有2个大型数据集。
第一个数据集包含约1.3亿个条目。
第二个数据集包含约40000个条目。
从MySQL表中获取数据。
我需要进行交叉联接,但是我得到了
java.sql.SQLException: GC overhead limit exceeded
在Scala中执行此操作的最佳最佳技术是什么?
以下是我的代码段:
val df1 = (spark.read.jdbc(jdbcURL,configurationLoader.mysql_table1,"id",100,100000,40, MySqlConnection.getConnectionProperties))
val df2 = (spark.read.jdbc(jdbcURL,configurationLoader.mysql_table2, MySqlConnection.getConnectionProperties))
val df2Cache = df2.repartition(40).cache()
val crossProduct = df1.join(df2Cache)
df1是较大的数据集,而df2是较小的数据集。
答案 0 :(得分:4)
130M * 40K = 52万亿条记录是存储此数据所需的52 TB内存,这是假设我们假设每条记录为1个字节,这肯定是不正确的。如果多达64个字节(我认为这也是一个非常保守的估计),则仅需要3.32 PB的内存即可存储数据。这是一个非常大的数目,因此,除非您拥有一个非常大的集群并在该集群内拥有非常快的网络,否则您可能需要重新考虑算法以使其工作。
也就是说,当您对两个SQL数据集/数据帧执行join
时,Spark用于存储联接结果的分区数将由spark.sql.shuffle.partitions
属性控制(请参见here)。您可能希望将其设置为非常大的数目,并将执行器的数目设置为最大数量。然后,您也许可以将处理过程进行到最后。
此外,您可能需要研究spark.shuffle.minNumPartitionsToHighlyCompress
选项;如果将其设置为小于随机播放分区的数量,则可能会增加内存。请注意,在最近的Spark版本之前,此选项是一个硬编码常量,设置为2000,因此根据环境的不同,您只需要将spark.sql.shuffle.partitions
设置为大于2000的数字即可使用它。
答案 1 :(得分:1)
同意弗拉基米尔,想增加点数。
请参见MapStatus将spark.sql.shuffle.partitions
设置为2001
(old approach)(默认为200)。
弗拉基米尔(Vladimir)在回答中提到的新方法(spark.shuffle.minNumPartitionsToHighlyCompress
)。
为什么要更改? : MapStatus has 2000 hardcoded SPARK-24519
它将采用不同的算法进行处理
def apply(loc: BlockManagerId, uncompressedSizes: Array[Long]): MapStatus = {
if (uncompressedSizes.length > minPartitionsToUseHighlyCompressMapStatus) {
HighlyCompressedMapStatus(loc, uncompressedSizes)
} else {
new CompressedMapStatus(loc, uncompressedSizes)
}
}
HighlyCompressedMapStatus
:
一个MapStatus实现,可存储巨大的精确尺寸 块,该块大于spark.shuffle.accurateBlockThreshold。 它存储其他非空块的平均大小以及一个位图 跟踪哪些块为空。
spark.shuffle.accurateBlockThreshold-see here:在HighlyCompressedMapStatus
中压缩随机播放块的大小时,如果它超过此配置,我们将准确记录该大小。通过避免在提取随机分组时低估随机分组的大小,有助于防止OOM。
CompressedMapStatus
:
一个MapStatus实现,可跟踪每个块的大小。尺寸 每个块用一个字节表示。
还设置为您的spark-submit
--conf spark.yarn.executor.memoryOverhead=<10% of executor memory> -- conf spark.shuffle.compress=true --conf spark.shuffle.spill.compress=true
在两种情况下,压缩将使用spark.io.compression.codec
结论 :大型任务应使用
HighlyCompressedMapStatus
,执行程序的内存开销可以占执行程序内存的10%。>
答案 2 :(得分:0)
将SPARK_EXECUTOR_MEMORY增加到更高的值,然后重新分区到更多分区