1. 程式人生 > >Spark性能調優之道——解決Spark數據傾斜(Data Skew)的N種姿勢

Spark性能調優之道——解決Spark數據傾斜(Data Skew)的N種姿勢

sca ace 便是 triplet 大小 spark 構建 由於 itl

原文:http://blog.csdn.net/tanglizhe1105/article/details/51050974

背景

很多使用Spark的朋友很想知道rdd裏的元素是怎麽存儲的,它們占用多少存儲空間?本次我們將以實驗的方式進行測試,展示rdd存儲開銷性能。
關於rdd的元素怎麽存儲,Spark裏面實現了好幾種不同類型的rdd,如最常見的MapPartitionsRDD,它處理map,filter,mapPartition等不引起shuffle的算子;再如ShuffledRDD它由shuffle操作生成的;像GraphX裏面的VertexRDD、EdgeRDD和TripletRDD,它們是分區內構建了大量索引得rdd。不同的rdd擁有不同的元素存儲機制,這些機制由rdd具體的分區對象來實現。關於rdd分區對象的存儲方式,由於內容過多,這裏不便介紹。

測試方法論

rdd到底占用多少空間,使用spark web ui的Executors查看是不夠的,它只能顯示executor目前已使用內存空間大小,並不能跟蹤每個rdd空間使用情況。好在spark提供了cache功能,它能使我們手動控制rdd在內存中貯存。若另外一個rdd使用已cache的rdd,那麽它的輸入便是cached rdd,rdd的輸入在web ui的job信息裏是可以查看的。本實驗的主要方法便是如此

val a = sc.parallelize( 1 to 1024*1024, 1).cache()
a.count()
val b = a.map( x=> (x, x)).cache()
b.count()
val c = b.map(x => x)
c.count()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

那麽b.count()提交的job的輸入能查看rdd a占用的內存空間大小,c.count()使得我們能查看rdd b占用的內存空間大小。

結果

元素數目元素類型rdd占用空間大小
1M Int 32MB
1M (Int, Int) 48MB
1M (Int, Int, Int) 120MB
1M Long 32MB
1M (Long, Long) 56MB
1M (Long, Long, Long) 120MB
1G Int 32GB
1G (Int, Int) 48GB
1G (Int, Int, Int) 120GB
1G Long 32GB
1G (Long, Long) 56GB
1G (Long, Long, Long) 120GB
10G Int 240GB
10G Long 246.7GB

本實驗1M使用單個分區,1G使用80個分區(10個節點),10G使用144個分區(18個節點)

1M與1G元素規模的結果吻合的太好了,以至於我都有不敢相信,可是測試出來的結果就是這樣的,這也證明spark在數據規模可擴展性方面真是太完美了。
關於每條元素的存儲開銷,若元素是Java對象存儲,那麽每條元素至少會帶入18自己額外開銷,若以基本數據類型存儲,則不會帶入額外開銷。
測試結果有一些詭異的地方:
相同元素規模情況下,Int與Long占用空間相同,(Int, Int)與(Long, Long)不同,但(Int, Int, Int)與(Long, Long, Long)又相同。
1M Int凈存儲空間為4MB,但占用32MB空間,且占用空間一般呈整數樣式。

Spark性能調優之道——解決Spark數據傾斜(Data Skew)的N種姿勢