我有一个>关于mysql的5GB表。我希望将该表作为数据帧加载到spark上,并从中创建一个镶木地板文件。
这是我的python函数来完成这项工作:
def import_table(tablename):
spark = SparkSession.builder.appName(tablename).getOrCreate()
df = spark.read.format('jdbc').options(
url="jdbc:mysql://mysql.host.name:3306/dbname?zeroDateTimeBehavior=convertToNull
",
driver="com.mysql.jdbc.Driver",
dbtable=tablename,
user="root",
password="password"
).load()
df.write.parquet("/mnt/s3/parquet-store/%s.parquet" % tablename)
我正在运行以下脚本来运行我的spark应用程序:
./bin/spark-submit ~/mysql2parquet.py --conf "spark.executor.memory=29g" --conf "spark.storage.memoryFraction=0.9" --conf "spark.executor.extraJavaOptions=-XX:-UseGCOverheadLimit" --driver-memory 29G --executor-memory 29G
当我在具有30 GB的EC2实例上运行此脚本时,它会失败并显示java.lang.OutOfMemoryError: GC overhead limit exceeded
与此同时,我只使用了1.42 GB的总内存。
以下是带有堆栈跟踪的完整控制台输出:https://gist.github.com/idlecool/5504c6e225fda146df269c4897790097
我不确定我做错了什么,或者火花不适合这个用例。我希望火花是。
答案 0 :(得分:2)
下面提供了关于spark的内存管理的一些粗略解释,你可以从官方文档中阅读更多关于它的内容,但这是我的看法:
我认为选项“spark.storage.memoryFraction = 0.9”在你的情况下是有问题的,粗略地说,执行器有三种类型的内存可以分配,首先是你设置为90%的存储内存执行程序内存,即大约~27GB,用于保存持久数据集。
第二个是用于执行计算的堆内存,对于你正在进行机器学习或大量计算的情况,通常设置为高,这在你的情况下是不够的,你的程序需要有更高的堆内存是导致此错误的原因。
第三种类型的存储器是shuffle memory,用于在不同分区之间进行通信。如果您在dataframes / rdd之间进行大量连接或者通常需要大量网络开销,则需要将其设置为高值。这可以通过设置“spark.shuffle.memoryFraction”
进行配置所以基本上你可以通过使用这两个设置来设置内存分数,在shuffle和存储内存之后可用的其余内存进入堆。
由于存储分数很高,程序可用的堆内存非常小。您需要使用这些参数来获得最佳值。由于输出的是镶木地板文件,因此通常需要更大的堆空间,因为程序需要计算压缩。我建议您为以下设置。这个想法是你没有做任何需要大量shuffle记忆的操作,因此它可以保持很小。此外,您不需要如此大量的存储空间。
“spark.storage.memoryFraction = 0.4” “spark.shuffle.memoryFraction = 0.2”
有关这方面的更多信息,请点击此处:
https://spark.apache.org/docs/latest/configuration.html#memory-management
答案 1 :(得分:0)
感谢Gaurav Dhama感谢explanation
,您可能还需要将myController
设置为 -XX:-UseGCOverheadLimit 。