我想了解代码存储在哪个节点(驱动程序或工作程序/执行程序)
df.cache() //df is a large dataframe (200GB)
具有更好的性能:使用sql cachetable
或cache()
。我的理解是,其中一个是懒惰的,另一个是渴望的。
答案 0 :(得分:2)
df.cache()
调用persist()
方法,该方法在存储级别上存储为MEMORY_AND_DISK
,但您可以更改存储级别
persist()
方法调用
sparkSession.sharedState.cacheManager.cacheQuery()
当你看到cacheTable
的代码时,它也会调用相同的代码
sparkSession.sharedState.cacheManager.cacheQuery()
这意味着两者都相同并且延迟评估(仅在执行操作时评估),除了persist
方法可以存储为提供的存储级别,这些是可用的存储级别< / p>
您还可以使用未延迟评估的SQL CACHE TABLE
并将整个表存储在内存中,这也可能导致OOM
摘要: cache()
,persist()
,cacheTable()
进行了延迟评估,需要执行一项操作,以便在SQL CACHE TABLE
渴望之前工作
请参阅此处查看details!
您可以根据自己的要求选择!
希望这有帮助!
答案 1 :(得分:1)
火花内存。这是由Apache Spark管理的内存池。可以将其大小计算为
(“Java Heap” – “Reserved Memory”) * spark.memory.fraction, and with Spark 1.6.0 defaults it gives us (“Java Heap” – 300MB) * 0.75.
。例如,如果有4GB堆,则该池的大小为2847MB。整个池分为两个区域-存储内存和执行内存,它们之间的边界由spark.memory.storageFraction参数设置,默认值为0.5。这种新的存储器管理方案的优点在于该边界不是静态的,并且在存储器压力的情况下该边界将被移动,即,一个区域将通过从另一区域借用空间来增长。我将稍后讨论“移动”此边界,现在让我们集中讨论如何使用此内存:
1. Storage Memory.
此池用于存储Apache Spark缓存的数据和临时空间序列化数据“展开”。同样,所有“广播”变量都作为缓存块存储在此处。如果您感到好奇,这里是展开代码。如您所见,它并不需要有足够的内存来供展开块使用-如果没有足够的内存来容纳整个展开的分区,则在所需的持久性级别允许的情况下,它将直接将其放入驱动器中。从“广播”开始,所有广播变量都以MEMORY_AND_DISK持久性级别存储在缓存中。
2. Execution Memory.
该池用于存储执行Spark任务期间所需的对象。例如,它用于在内存中的“映射”侧上存储洗牌中间缓冲区,也用于存储哈希表以进行哈希聚合。如果没有足够的可用内存,此池还支持在磁盘上溢出,但是其他线程(任务)无法强行驱逐该池中的块。
好的,现在让我们集中讨论存储内存和执行内存之间的边界。由于执行内存的性质,您不能从该池中强制退出块,因为这是中间计算中使用的数据,并且如果找不到该内存所引用的块,则需要该内存的过程只会失败。但是对于存储内存却并非如此-它只是存储在RAM中的块的高速缓存,如果我们从那里逐出该块,我们就可以更新该块的元数据,以反映该块已被驱逐到HDD(或只是删除了) ,并尝试访问此块,Spark将从硬盘上读取它(或重新计算,以防您的持久性级别不允许溢出到硬盘上)。
因此,我们可以从存储内存中强制退出该块,但不能从执行内存中退出。执行内存池何时可以从存储内存借用一些空间?它发生在以下情况之一:
“存储内存”池中有可用空间,即缓存的块不会使用那里的所有可用内存。然后,它只是减小了存储内存池的大小,增加了执行内存池。
存储内存池的大小超过了初始存储内存区域的大小,并且已利用了所有这些空间。这种情况会导致强制从存储内存池中逐出块,除非它达到其初始大小。
反过来,只有在执行内存池中有可用空间的情况下,存储内存池才能从执行内存池借用一些空间。
您可能还记得,初始存储内存区域大小的计算方式为“火花内存” * spark.memory.storageFraction =(“ Java堆” –“保留内存”)* spark.memory.fraction * spark.memory.storageFraction。使用默认值时,该值等于(“Java Heap” – 300MB) * 0.75 * 0.5 = (“Java Heap” – 300MB) * 0.375. For 4GB heap this would result in 1423.5MB of RAM in initial Storage Memory region
。
答案 2 :(得分:0)
persist
(或cacheTable
)方法标记DataFrame在内存中缓存(或磁盘,如果需要,如另一个答案所示),但只有在对其执行操作时才会发生这种情况。 DataFrame,只是以懒惰的方式,即如果你最终只读取100行,则只缓存那100行。创建一个临时表并使用cache
非常渴望它将立即缓存整个表。哪个性能更高取决于您的情况。我使用普通DataFrame .count()
做的一件事就是立即立即调用with open('badphrases.txt') as f:
content = f.readlines()
badphrases = [x.strip() for x in content]
with open('allphrases.txt') as f:
content = f.readlines()
allphrases = [x.strip() for x in content]
,强制缓存DataFrame,并且无需注册临时表等。
答案 3 :(得分:0)
只需加上我的25美分。 SparkDF.cache()会将数据加载到执行程序内存中。 它不会加载到驱动程序存储器中。这是所需要的。 这是我刚运行df.cache()。count()后50%的数据加载快照。
如 koiralo 所述,Cache()保留在内存和磁盘中,并且也可以进行惰性计算。
Cachedtable()存储在磁盘上,因此可以抵抗节点故障。