我正在学习Spark,并试图进一步了解Spark如何使用和管理内存。我正在以local[*]
主机配置在本地模式下运行Spark应用程序。
简而言之,我有很多非常小的数据框(2000行x 5列),其中有一个uid
列,我试图加入一个更大的数据框(2000行x 150列),也有一个{ {1}}列。我的联接代码:
uid
当我最终调用 df=df.join(
self.sqlContext.createDataFrame(join1,schema=['uid', 'join1']),on='uid')
print(f"Joined join1")
df=df.join(
self.sqlContext.createDataFrame(join2,schema=['uid', 'join2']),
on='uid')
print(f"Joined join2")
df=df.join(
self.sqlContext.createDataFrame(join3,schema=['uid', 'join3']),
on='uid')
print(f"Joined join3")
df=df.join(
self.sqlContext.createDataFrame(join4,schema=['uid', 'join4']),
on='uid')
print(f"Joined join4")
作为强制评估的动作时,我发现Spark成功将数据连接在一起,但是随后在收集阶段遇到了内存错误:
df.take(100)
为纠正这种情况,我每加入几个java.lang.OutOfMemoryError: Unable to acquire 100 bytes of memory, got 0
就可以强制评估:
df.count()
我可能需要进行40个联接,每10个联接,我将强制使用 df=df.join(
self.sqlContext.createDataFrame(join1,schema=['uid', 'join1']),on='uid')
print(f"Joined join1")
df=df.join(
self.sqlContext.createDataFrame(join2,schema=['uid', 'join2']),
on='uid')
print(f"Joined join2")
df=df.join(
self.sqlContext.createDataFrame(join3,schema=['uid', 'join3']),
on='uid')
print(f"Joined join3")
print(df.count()) # force evaluation
print(df.cache()) # cache new dataframe
df=df.join(
self.sqlContext.createDataFrame(join4,schema=['uid', 'join4']),
on='uid')
print(f"Joined join4")
进行评估。当我尝试这种方法时,我可以执行我最后的df.count()
操作。
我的问题是-为什么这样做?如果我们直到最后一个{{1 }}。但是,如果我们在执行连接时逐步评估和缓存,则collect()
会起作用。在SparkUI中,我看到有许多collect()
正在发生,但是我不太了解执行准确的早期评估如何减少最终collect()
期间驱动程序的内存负载。