![](/img/trans.png)
[英]Sorting an RDD in Apache Spark using mapPartitions and reduce
[英]Spark RDD- map vs mapPartitions
我通讀了map和mapPartitions之間的理論差異,並且很清楚何時在各種情況下使用它們。
但是我下面描述的問題更多地取決於GC活動和內存(RAM)。 有關問題,請閱讀以下內容:
=>我編寫了一個映射函數,將Row轉換為String。 因此,RDD [org.apache.spark.sql.Row]的輸入將映射到RDD [String]。 但是,通過這種方法,將為RDD的每一行創建映射對象。 因此,創建如此大量的對象可能會增加GC活動。
=>要解決以上問題,我想到了使用mapPartitions。 因此,該對象數等於分區數。 mapPartitions提供Iterator作為輸入,並接受return和java.lang.Iterable。 但是大多數Iterable(例如Array,List等)都在內存中。 那么,如果我有大量數據,那么以這種方式創建Iterable會導致內存不足嗎? 還是在這里應該使用其他任何集合(java或scala)(以防萬一內存開始填充到磁盤上)? 還是僅在RDD完全在內存中的情況下才使用mapPartitions?
提前致謝。 任何幫助將不勝感激。
如果您考慮使用JavaRDD.mapPartitions
則需要使用FlatMapFunction
(或某些類似DoubleFlatMapFunction
變體),該函數將返回Iterator
not Iterable
。 如果底層收集很懶,那么您就不用擔心。
RDD.mapPartitions
接受從Iterator
到Iterator
的函數。
通常,如果您使用參考數據,則可以用map
替換mapPartitions
並使用靜態成員來存儲數據。 這將具有相同的占用空間,並且更易於編寫。
回答有關mapPartition(f:Iterator => Iterator)的問題。 它是懶惰的,並且不將整個分區保存在mem中。 Spark將使用此(我們可以認為它是FP術語中的Functor)Iterator => Iterator函數,並將其重新編譯為自己的代碼以執行。 如果分區太大,它將在下一個隨機播放點之前溢出到磁盤。 所以不用擔心
需要提到的一件事是,您可以通過執行以下操作來強制函數將數據具體化為內存:
rdd.mapPartition(
partitionIter => {
partitionIter.map(do your logic).toList.toIterator
}
)
toList
將強制Spark將整個分區的數據具體化為mem,因此請注意這一點,因為類似於toList
ops將打破功能鏈的惰性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.