1. 程式人生 > >一起學spark(12)-- 關於RDD和DataFrame 的快取

一起學spark(12)-- 關於RDD和DataFrame 的快取

(1)Rdd持久化

   當呼叫RDD的persist()或者cache()方法時,這個RDD的分割槽會被儲存到快取區中,Spark會根據spark.storage.memoryFraction 限制用來快取的記憶體佔整個JVM堆空間的比例大小,如果超出限制,舊的分割槽資料會被移出記憶體。

   Spark預設的 cache() 操作會以MEMORY_ONLY 的儲存等級持久化資料,意味著快取新的RDD分割槽時空間不夠,舊的分割槽就會丟失,當用到這些分割槽時,再根據血統進行重算。

   但persis()可以以MEMORY_AND_DISK 儲存,記憶體中放不下的舊分割槽會寫入磁碟,當再次需要時再從磁碟上讀取回來,因此帶來更穩定的效能表現。

1.僅記憶體快取,Spark將RDD作為為序列化的Java物件儲存於記憶體中。語句如下

my_rdd.cache()
my_rdd.persist() #預設就是記憶體
my_rdd.persist(StorageLevel.MEMORY_ONLY)
序列化形式:以序列化的Java物件儲存在記憶體,比未序列化在空間上利用更高,因為資料更緊湊。缺點是佔用更多的CPU,因為物件在每次讀寫時都會做序列化/反序列化。當快取RDD時,所選擇的序列化器很重要。
my_rdd.persist(StorageLevel.MEMORY_ONLY_SER)
2.存於記憶體和磁碟:無法完全放入記憶體的分割槽溢寫到磁碟
my_rdd.persist(StorageLevel.MEMORY_AND_DISK)
my_rdd.persist(StorageLevel.MEMORY_AND_DISK_SER) #序列化
3.僅存於磁碟,但CPU負載極高
my_rdd.persist(StorageLevel.DISK_ONLY)

4.堆外儲存,在這種情況下,序列化的RDD將儲存在Tachyon的堆外儲存上,這個選項有很多好處,最重要的一個好處是可以在executor及其他應用之間共享一個記憶體池,減少垃圾回收帶來的消耗。

my_rdd.persist(StorageLevel.OFF_HEAP)
如果應用程式是用Python寫的,則不管是否選擇了序列化的儲存級別,RDD總是序列化的。

如果要從快取中移除RDD,要麼等著它以最近最久未使用(LRU)方式被消除,要麼呼叫unpersist()方法
my_rdd.unpersist()

(2)SparkSQL 快取

SparkSQL快取的表是以列式儲存在記憶體中的,使得在做查詢時,不需要對整個資料集進行全部掃描,僅需要對需要的列進行掃描,所以效能有很大提升。

如果資料是以列式儲存的,SparkSQL就能按列自動選擇最優的壓縮編碼器,對它調優以減少記憶體使用及垃圾回收壓力。DataFrame本身也是rdd,所以其實也可以直接按rdd的快取方式快取DataFrame

dataFrame.persist() #直接快取dataFrame
#建議採用以下方式快取
dataFrame.registerTempTable("tab_name")
hiveCtx.cacheTable("tab_name")
RDD持久化在執行action操作時才會被持久化,而SparkSQL中快取表則在請求表時被快取。

為釋放記憶體,需要手動從快取中刪除表

dataFrame.unpersist()
hiveCtx.uncacheTable("tab_name") #基於cacheTable 方法