Java-Spark系列10-Spark性能調優概述 一.Spark 性能優化概述 二.運行環境優化 三.RDD算子優化 四.參數微調 五.數據傾斜 六. Spark常用的調優參數 參考:

一.Spark 性能優化概述

首先筆者能力優先,使用Spark有一段時間,如下是筆者的工作經驗的總結。

Spark任務運行圖:


Spark的優化思路:
一般是從3個層面進行Spark程序的優化:

  1. 運行環境優化
  2. RDD算子優化
  3. 參數微調

二.運行環境優化

2.1 數據本地性

我們知道HDFS的數據文件存儲在不同的datanode,一般數據副本數量是3,因爲Spark計算的數據量比較大,如果數據不在本節點,需要通過網絡去其它的datanode讀取數據。

所以此時我們可以通過提高數據本地性,減少網絡傳輸,來達到性能優化的目的。

  1. 計算和存儲同節點(executor和HDFS的datanode、hbase的region server同節點)
  2. executor數目合適: 如果100個數據界定,3個計算節點,就有97份網絡傳遞,所以此種情況可以適當增加計算節點。
  3. 適當增加數據副本數量

2.2 數據存儲格式

推薦使用列式存儲格式: parquet.
parquet存在如下優先:

  1. 相同數據類型的數據有很高壓縮比
  2. Hive主要支持ORC、也支持parquet

三.RDD算子優化

3.1 儘可能複用同一個RDD

每創建一個RDD都會帶來性能的開銷,儘可能的對同一個RDD做算子操作,而不要頻繁創建新的
RDD。

3.2 對多次使用的RDD進行持久化

如果RDD的算子特別多,需要頻繁多次操作同一個RDD,最好的辦法是將該RDD進行持久化,

四.參數微調

  1. num-executors
    參數說明:該參數用於設置每個Executor進程的內存。Executor內存的大小,很多時候直接決定了Spark作業的性能,而且跟常見的JVM OOM異常,也有直接的關聯。

  2. executor-cores
    參數說明:該參數用於設置每個Executor進程的CPU core數量。

  3. driver-memory
    參數說明:該參數用於設置Driver進程的內存。

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

  5. spark.storage.memoryFraction
    參數說明:該參數用於設置RDD持久化數據在Executor內存中能佔的比例,默認是0.6。

  6. spark.shuffle.memoryFraction
    參數說明:該參數用於設置shuffle過程中一個task拉取到上個stage的task的輸出後,進行聚合操作時能夠使用的Executor內存的比例,默認是0.2。

資源參數參考示例:

./bin/spark-submit \
  --master yarn-cluster \
  --num-executors 100 \
  --executor-memory 6G \
  --executor-cores 4 \
  --driver-memory 1G \
  --conf spark.default.parallelism=1000 \
  --conf spark.storage.memoryFraction=0.5 \
  --conf spark.shuffle.memoryFraction=0.3 \

五.數據傾斜

絕大多數task執行得都非常快,但個別task執行極慢。比如,總共有1000個task,997個task都在1分鐘之內執行完了,但是剩餘兩三個task卻要一兩個小時。這種情況很常見。

數據傾斜圖例:


解決數據傾斜一般有如下幾種常用方法:

  1. 使用Hive ETL預處理數據
    先使用Hive進行預處理數據,也就是使用Hive先計算一層中間數據,Spark從中間層數據開始計算。

  2. 過濾少數導致傾斜的key
    如果發生導致傾斜的key非常少,可以將Spark任務拆分爲包含 導致傾斜的key的任務和不包含key的任務。

  3. sample採樣傾斜key單獨進行join
    通過採樣,提前預估會發生數據傾斜的key,然後將一個join拆分爲兩個join,其中一個不包含該key,一個只包含該key,最後將結果集進行union。

  4. 調整並行度
    調整Shuffle並行度,數據打散

  5. 廣播小數據集
    適用於一個大表,一個小表
    不用join連接操作,而改用Broadcast變量與map模擬join操作,完全規避shuffle操作
    spark.sql: spark.sql.autoBroadcastJoinThreshold=104857600

  6. 增加隨機前綴
    對發生傾斜的RDD增加隨機前綴
    對另外一個RDD等量擴容
    如果少量的key發生傾斜,可以先過濾出一個單獨的RDD,對另外一個RDD同理吹,join之後再合併

六. Spark常用的調優參數

6.1 在內存中緩存數據

Spark SQL可以通過調用Spark.catalog.cachetable ("tableName")或DataFrame.cache()來使用內存中的columnar格式緩存表。然後Spark SQL將只掃描所需的列,並自動調優壓縮以最小化內存使用和GC壓力。你可以調用spark.catalog.uncacheTable("tableName")從內存中刪除表。

內存緩存的配置可以在SparkSession上使用setConf方法或者使用SQL運行SET key=value命令來完成。

參數名 默認值 參數說明 啓始版本
spark.sql.inMemoryColumnarStorage.compressed true 當設置爲true時,Spark SQL會根據數據統計自動爲每列選擇壓縮編解碼器。 1.0.1
spark.sql.inMemoryColumnarStorage.batchSize 10000 控制柱狀緩存的批大小。更大的批處理大小可以提高內存利用率和壓縮,但在緩存數據時可能會帶來OOMs風險。 1.1.1

6.2 其它配置項

還可以使用以下選項調優查詢執行的性能。隨着更多的優化被自動執行,這些選項可能會在未來的版本中被棄用。

參數名 默認值 參數說明 啓始版本
spark.sql.files.maxPartitionBytes 134217728 (128 MB) 讀取文件時裝入單個分區的最大字節數。此配置僅在使用基於文件的源(如Parquet、JSON和ORC)時有效。 2.0.0
spark.sql.files.openCostInBytes 4194304 (4 MB) 打開一個文件的估計成本,由可以在同一時間掃描的字節數來衡量。當將多個文件放入一個分區時使用。最好是高估,那麼帶有小文件的分區將比帶有大文件的分區更快(這是首先安排的)。此配置僅在使用基於文件的源(如Parquet、JSON和ORC)時有效。 2.0.0
spark.sql.files.minPartitionNum Default Parallelism 建議的(不是保證的)最小分割文件分區數。如果沒有設置,默認值是' spark.default.parallelism '。此配置僅在使用基於文件的源(如Parquet、JSON和ORC)時有效。 3.1.0
spark.sql.broadcastTimeout 300 broadcast join 等待時間的超時(秒) 1.3.0
spark.sql.autoBroadcastJoinThreshold 10485760 (10 MB) 配置在執行聯接時將廣播到所有工作節點的表的最大字節大小。通過將此值設置爲-1,可以禁用廣播。注意:目前統計只支持運行ANALYZE TABLE COMPUTE statistics noscan命令的Hive Metastore表。 1.1.0
spark.sql.shuffle.partitions 200 配置將數據變換爲連接或聚合時要使用的分區數量。 1.1.0
spark.sql.sources.parallelPartitionDiscovery.threshold 32 配置閾值以啓用作業輸入路徑的並行列出。如果輸入路徑數大於該閾值,Spark將通過Spark分佈式作業列出文件。否則,它將退回到順序列表。此配置僅在使用基於文件的數據源(如Parquet、ORC和JSON)時有效。 1.5.0
spark.sql.sources.parallelPartitionDiscovery.parallelism 10000 配置作業輸入路徑的最大列出並行度。如果輸入路徑的數量大於這個值,它將被降低到使用這個值。與上面一樣,此配置僅在使用基於文件的數據源(如Parquet、ORC和JSON)時有效。 2.1.1

6.3 SQL查詢連接的hint

join策略提示BROADCAST、MERGE、SHUFFLE_HASH和SHUFFLE_REPLICATE_NL,在將指定的關係加入到另一個關係時,指示Spark對每個指定的關係使用暗示策略。例如,在表' t1 '上使用BROADCAST提示時,廣播加入(廣播散列連接或廣播嵌套循環聯接取決於是否有等值連接鍵)與t1的構建方面將由火花即使大小的優先表t1的建議的統計配置spark.sql.autoBroadcastJoinThreshold之上。

當連接兩端指定了不同的連接策略提示時,Spark會優先考慮BROADCAST提示而不是MERGE提示,優先考慮SHUFFLE_HASH提示而不是SHUFFLE_REPLICATE_NL提示。當雙方都指定了BROADCAST提示或SHUFFLE_HASH提示時,Spark將根據連接類型和關係的大小選擇構建端。

請注意,不能保證Spark會選擇提示中指定的連接策略,因爲特定的策略可能不支持所有的連接類型。

-- We accept BROADCAST, BROADCASTJOIN and MAPJOIN for broadcast hint
SELECT /*+ BROADCAST(r) */ * FROM records r JOIN src s ON r.key = s.key

Coalesce hint允許Spark SQL用戶控制輸出文件的數量,就像Dataset API中的Coalesce、repartition和repartitionByRange一樣,它們可以用於性能調優和減少輸出文件的數量。COALESCE hint只有一個分區號作爲參數。“REPARTITION”提示有一個分區號、列或它們都作爲參數。“REPARTITION_BY_RANGE”提示必須有列名,分區號是可選的。

SELECT /*+ COALESCE(3) */ * FROM t
SELECT /*+ REPARTITION(3) */ * FROM t
SELECT /*+ REPARTITION(c) */ * FROM t
SELECT /*+ REPARTITION(3, c) */ * FROM t
SELECT /*+ REPARTITION_BY_RANGE(c) */ * FROM t
SELECT /*+ REPARTITION_BY_RANGE(3, c) */ * FROM t

6.4 自適應查詢執行

Adaptive Query Execution (AQE)是Spark SQL中的一種優化技術,它利用運行時統計信息來選擇最高效的查詢執行計劃。默認情況下AQE是禁用的。Spark SQL可以使用Spark.SQL.adaptive.enabled的傘配置來控制是否打開/關閉。從Spark 3.0開始,AQE中有三個主要特性,包括合併shuffle後分區、將排序合併連接轉換爲廣播連接以及傾斜連接優化。

6.5 合併分區後重新組合

當spark.sql.adaptive.enabled和spark.sql.adaptive.coalescePartitions.enabled配置都爲true時,該特性根據map輸出統計信息來合併post shuffle分區。這個特性簡化了運行查詢時shuffle分區號的調優。您不需要設置合適的shuffle分區號來適合您的數據集。一旦您通過Spark .sql. adaptive.coalescepartitions . initialpartitionnum配置設置了足夠大的初始shuffle分區數,Spark就可以在運行時選擇適當的shuffle分區號。

參數名 默認值 參數說明 啓始版本
spark.sql.adaptive.coalescePartitions.enabled true 當true和Spark .sql. adaptive_enabled爲true時,Spark會根據目標大小(由Spark .sql. adaptive_advisorypartitionsizeinbytes指定)合併連續的shuffle分區,以避免過多的小任務。 3.0.0
spark.sql.adaptive.coalescePartitions.minPartitionNum Default Parallelism 合併後的最小洗牌分區數。如果不設置,則默認爲Spark集羣的默認並行度。此配置僅在spark.sql. adaptive.net enabled和spark.sql. adaptive.net coalescepartitions .enabled同時啓用時有效。 3.0.0
spark.sql.adaptive.coalescePartitions.initialPartitionNum 200 合併前的初始shuffle分區數。默認情況下它等於spark.sql.shuffle.partitions。此配置僅在spark.sql. adaptive.net enabled和spark.sql. adaptive.net coalescepartitions .enabled同時啓用時有效。 3.0.0
spark.sql.adaptive.advisoryPartitionSizeInBytes 64 MB 自適應優化期間shuffle分區的建議大小(當spark.sql. adaptive_enabled爲true時)。當Spark對小shuffle分區或斜shuffle分區進行合併時生效。 3.0.0

6.6 將排序合併聯接轉換爲廣播聯接

當任何連接側的運行時統計數據小於廣播散列連接閾值時,AQE將排序合併連接轉換爲廣播散列連接。這不是一樣有效規劃一個廣播散列連接首先,但這總比繼續做分類合併加入,我們可以節省連接雙方的排序,並在本地讀取洗牌文件節省網絡流量(如果spark.sql.adaptive.localShuffleReader.enabled被設置爲true)

6.7 優化傾斜連接

數據傾斜會嚴重降低連接查詢的性能。該特性通過將傾斜任務拆分(如果需要的話還可以複製)爲大小大致相同的任務,動態處理排序-合併連接中的傾斜任務。當spark.sql.adaptive.enabled和spark.sql.adaptive.skewJoin.enabled配置同時啓用時生效。

參數名 默認值 參數說明 啓始版本
spark.sql.adaptive.skewJoin.enabled true 當true和Spark .sql.adaptive.enabled爲true時,Spark通過拆分(並在需要時複製)傾斜分區來動態處理排序-合併連接中的傾斜。 3.0.0
spark.sql.adaptive.skewJoin.skewedPartitionFactor 10 如果一個分區的大小大於這個因子乘以中值分區大小,並且大於spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes,則認爲該分區是傾斜的。 3.0.0
spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes 256MB 如果分區的字節大小大於這個閾值,並且大於spark.sql.adaptive.skewJoin.skewedPartitionFactor乘以分區中值大小,則認爲該分區是傾斜的。理想情況下,該配置應該設置爲大於spark.sql.adaptive.advisoryPartitionSizeInBytes。 3.0.0

參考:

  1. http://spark.apache.org/docs/latest/rdd-programming-guide.html
  2. https://tech.meituan.com/2016/04/29/spark-tuning-basic.html
  3. https://blog.csdn.net/meihao5/article/details/81084876
  4. http://spark.apache.org/docs/latest/sql-performance-tuning.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章