1、代碼中盡量避免group by函數,如果需要數據聚合,group形式的為rdd.map(x=>(x.chatAt(0),x)).groupbyKey().mapValues((x=>x.toSet.size)).collection() 改為 rdd.map(x=>(x.chatAt(0),x)).countByKey();或進行reduceByKey,效率會提高3倍。
2、parquet存儲的文件格式查詢會比sequenceFile快兩倍以上,當然這是在select * from的情況下,但其實100+列的情況下,我們做數據分析很少用到select * ,那么parquet列式存儲會更加高效,因為讀取一個Parquet文件時,需要完全讀取Footer的meatadata,Parquet格式文件不需要讀取sync markers這樣的標記分割查找。
3、spark.rdd.compress 參數,個參數決定了RDD Cache的過程中,RDD數據在序列化之后是否進一步進行壓縮再儲存到內存或磁盤上。當然是為了進一步減小Cache數據的尺寸,如果在磁盤IO的確成為問題或者GC問題真的沒有其它更好的解決辦法的時候,可以考慮啟用RDD壓縮。
4、spark.shuffle.manage 我建議使用hash,同時與參數spark.shuffle.consolidateFiles true並用。因為不需要對中間結果進行排序,同時合並中間文件的個數,從而減少打開文件的性能消耗。
5、首先,shuffle過程,與result過程都會將數據返回driver端,JVM參數過少會導致driver端老年代也塞滿,容易full GC,同時會經常發生GC,因為核數少,所以每個核可以承載更多的數據,那么一下子返回給driver,就塞滿新生代,發生GC。監控頁面就發現GC time比多核的要高。
6、這里的limit是直接limit全表的,並沒有做where分區limit。 同時left join自關聯,即便內存不夠的情況下,spark依舊會寫入磁盤,但任務相當的慢。
7、發現我們的數據基本沒有分庫,最好分一下庫,如果以后多個部門使用,那么在default中進行各部門數據的梳理生成,最終生成到不同的庫中,防止數據雜亂無章。
8、分表,我們現在的數據是按dt字段分區的,沒有分表,如果前台查詢沒有分區,將會造成OOM。 是否可以按照table_name_20161108這種方式,按日生成,那么select * from tablename 也不會造成Spark卡死,其他任務等待。
9、在一個executor實例中,多核會拉起多個task同時並行計算,會比單核計算要快很多。后續用例調整參數,增加與生產同等配置的情況下再進行測試。
10、注意一點,spark監控頁面與driver端共享監控頁面,可以去查看各個節點containner的運行情況,盡量少的直接點進去看DAG或task運行情況,否則大的任務task數據展示,也是容易導致JVM對內存溢出。
11、CPU瞬時的使用率大概在100-200%左右,最高持續6秒,隨后降至百分之2%左右
12、並發極端的情況還未完全測試,但以spark的原理,倘若第一個任務沒有占滿spark的總並發數,那么另一個任務將會在這些空閑的task中進行輪訓執行。 整個調度由DAG控制。
13、spark.speculation true 推測執行,這個參數用來比如有數據傾斜或者某個task比較慢的情況下,會另起一個task進行計算,哪個先完成就返回哪個結果集。但是在spark1.3版本的時候,有中間tmp文件缺失的情況,會報找不到hdfs路徑下的文件。所以,推測執行這個參數不知道在spark1.6是否修復,后續進行測試。
14、spark.task.maxFailures 10 這個參數的作用主要是在task失敗的情況之下,重試的次數,超過這個次數將會kill掉整個job 這種情況比如網絡IO fetch數據失敗等情況。
15、spark.storage.memoryFraction 0.5 這個參數 考慮穩定性GC與效率問題,決定使用0.5這個參數。
16、spark.sql.shuffle.partitions 200 經測試修改到400並沒有變得更快,是因為給的內存足以進行task的計算,在具體情況下代碼中set。
17、spark.kryoserializer.buffer.max 數據傳輸序列化最大值,這個通常用戶各服務器之間的數據傳輸,這里給到最大10g
18、spark.default.parallelism 3 可使一個core同時執行2-3個task,在代碼中通過傳入numPartitions 參數來改變。(還需深入測試)
19、spark.reducer.maxSizeInFlight 128M 在Shuffle的時候,Reducer端獲取數據會有一個指定大小的緩存空間,如果內存足夠大的情況下,可以適當的增大緩存空間,否則會spill到磁盤上影響效率。因為我們的內存足夠大。
20、spark.shuffle.file.buffer 128M ShuffleMapTask端通常也會增大Map任務的寫磁盤的緩存