Spark | SparkSql Insert Overwrite 小文件過多

SparkSql在執行Hive Insert Overwrite Table 操作時 ,默認文件生成數和表文件存儲的個數有關,但一般上游表存儲個數並非下游能控制的,這樣的話得考慮處理小文件問題。

小文件產生原因:
spark.sql.shuffle.partitions=200 ,spark sql默認shuffle分區是200個,如果數據量比較小時,寫hdfs時會產生200個小文件。

可嘗試通過以下操作來解決小文件過多問題,如下

Shuffle Partition 

--conf spark.sql.shuffle.partitions=10 \
--conf spark.default.parallelism=10 \

目前SparkSql中reduce階段的task個數取決於固定參數 spark.sql.shuffle.partition(默認值 200),注意,若一個作業一旦設置了該參數,它運行過程中的所有階段的reduce個數都是同一個值。

而對於不同的作業,以及同一個作業內的不同reduce階段,實際的數據量大小可能相差很大,例如reduce階段要處理的數據可能是10MB,也有可能是100GB, 如果使用同一個值對實際運行效率會產生很大影響,例如10MB的數據一個task就可以解決,如果 spark.sql.shuffle.partition使用默認值200的話,那麼10MB的數據就要被分成200個task處理,增加了調度開銷,影響運行效率。

而spark.default.parallelism 該參數用於設置每個stage的默認task數量。

值得注意的是,

spark.default.parallelism只有在處理RDD時纔會起作用,對SparkSql無效。

spark.sql.shuffle.partitions則是對sparks SQL專用的設置。

 

coalesce & repartition

rdd.toDF("name", "age", "address").coalesce(3).createOrReplaceTempView("tmp_table")
spark.sql("insert overwrite table t1 select name,age,address from tmp_table")


df.repartition(10).createOrReplaceTempView("tmp_table")
spark.sql("insert overwrite table t1 select name,age,address from tmp_table")

coalesce 和 repartition 都是對 RDD 重新分區。 coalesce 操作使用HashPartitioner 進行重分區,第一個參數爲重分區的數目,第二個爲是否進行 shuffle,默認情況下是 false。
repartition 操作是 coalesce 函數第二個參數爲 true 的實現。
使用 coalesce 操作 RDD 時需注意:
1)重新分區的數目需要小於原分區數據。
2)重新分區數目大於原來的分區數,那麼必須制定 shuffle 參數爲 true,否則分區數不變。

 

Distribute by 方式

distribute by是控制在map端如何拆分數據給reduce端的。hive會根據distribute by後面列,對應reduce的個數進行分發,默認是採用hash算法。大部分情況都用於解決Map輸出的文件大小不均,Reduce輸出文件大小不均,小文件過多,文件數過大等情況.

distribute by 控制map輸出結果的分發,相同字段的map輸出會發到一個reduce節點去處理;sort by爲每一個reducer產生一個排序文件。cluster by = distribute by + sort by,默認只能是升序。

 select name,age,address from tmp_table Distribute by name;

 

SparkSql自適應調整

 --conf spark.sql.adaptive.enabled=true \
 --conf spark.sql.adaptive.shuffle.targetPostShuffleInputSize=128000000 \

SparkSQL自適應框架可以通過設置shuffle partition的上下限區間,在這個區間內對不同作業不同階段的reduce個數進行動態調整。通過區間的設置,一方面可以大大減少調優的成本(不需要找到一個固定值),另一方面同一個作業內部不同reduce階段的reduce個數也能動態調整。

屬性名稱 默認值 備註
spark.sql.adaptive.enabled false 自適應執行框架的開關。
spark.sql.adaptive.minNumPostShufflePartitions 1 reduce個數區間最小值。
spark.sql.adaptive.maxNumPostShufflePartitions 500 reduce個數區間最大值。
spark.sql.adaptive.shuffle.targetPostShuffleInputSize 67108864 動態調整reduce個數的 partition 大小依據,如設置64MB,則reduce 階段每個task最少處理 64MB的數據。
spark.sql.adaptive.shuffle.targetPostShuffleRowCount 20000000 動態調整reduce個數的partition條數依據,如設置20000000則reduce階段每個task最少處理 20000000條的數據。

 

數據傾斜

Join中會經常碰到數據傾斜的場景,導致某些task處理的數據過多,出現很嚴重的長尾。目前SparkSQL沒有對傾斜的數據進行相關的優化處理。

SparkSQL自適應框架可以根據預先的配置在作業運行過程中自動檢測是否出現傾斜,並對檢測到的傾斜進行優化處理。

優化的主要邏輯是對傾斜的partition進行拆分由多個task來進行處理,最後通過union進行結果合併。

支持的 Join 類型:

join類型 備註
Inner 左/右表均可處理傾斜。
Cross 左/右表均可處理傾斜。
LeftSemi 只對左表處理傾斜。
LeftAnti 只對左表處理傾斜。
LeftOuter 只對左表處理傾斜。
RightOuter 只對右表處理傾斜。

參數設置:

spark.sql.adaptive.enabled false 自適應執行框架的開關。
spark.sql.adaptive.skewedJoin.enabled false 傾斜處理開關。
spark.sql.adaptive.skewedPartitionFactor 10 當一個 partition的size大小或大於該值(所有parititon大小的中位數) 且大於spark.sql.adaptive.skewedPartitionSizeThreshold,或者parition的條數大於該值(所有parititon條數的中位數)且大於 spark.sql.adaptive.skewedPartitionRowCountThreshold, 纔會被當做傾斜的partition進行相應的處理。
spark.sql.adaptive.skewedPartitionSizeThreshold 67108864 傾斜的partition大小不能小於該值。
spark.sql.adaptive.skewedPartitionRowCountThreshold 10000000 傾斜的partition條數不能小於該值。

 

Runtime執行計劃優化

SparkSQL的Catalyst優化器會將sql語句轉換成物理執行計劃,然後真正運行物理執行計劃。但是Catalyst轉換物理執行計劃的過程中,由於缺少Statistics統計信息,或者Statistics統計信息不準等原因,實際轉換的物理執行計劃可能並不是最優的,例如轉換爲SortMergeJoinExec,但實際BroadcastJoin更合適。

SparkSQL自適應執行框架會在物理執行計劃真正運行的過程中,動態的根據shuffle階段shuffle write的實際數據大小,來調整是否可以用 BroadcastJoin來代替SortMergeJoin,提高運行效率。

參數:

屬性名稱 默認值 備註
spark.sql.adaptive.enabled false 自適應執行框架的開關。
spark.sql.adaptive.join.enabled true 開關。
spark.sql.adaptiveBroadcastJoinThreshold 等於spark.sql.autoBroadcastJoinThreshold

運行過程中用於判斷是否滿足BroadcastJoin 條件

 


關於SparkSql 自適應調整最近官方正式發佈了Spark3.0,新特性中有涉及到SparkSql自適應查詢執行計劃的優化。

更多學習:

SparkSql 自適應: https://my.oschina.net/hblt147/blog/3006406

Spark官網:http://spark.apache.org/docs/latest/configuration.html

Spark3.0: https://www.iteblog.com/archives/9754.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章