1 前言
基于Spark 2.3.0測(cè)試筆記一:Shuffle到胃疼的初步測(cè)試結(jié)論,由于未經(jīng)聲明的參數(shù)行為變化, 2.3.0的性能對(duì)比慘到不行。本輪測(cè)試在之前的基礎(chǔ)上對(duì)2.3.0加上額外的參數(shù)設(shè)置spark.sql.statistics.fallBackToHdfs true進(jìn)行新一輪的性能測(cè)試,以期望令人滿意的結(jié)果。
2 測(cè)試數(shù)據(jù)
| benchmark | scale | fileformat | partitioned | link |
|---|---|---|---|---|
| TPCDS | 1T | parquet | true | https://github.com/yaooqinn/tpcds-for-spark |
3 實(shí)驗(yàn)對(duì)象
3.1 參照組
| baseline | modified | commit | link |
|---|---|---|---|
| 2.1.2 | true | 9ef23ae | https://github.com/yaooqinn/spark/tree/v2.1.2-based |
3.2 實(shí)驗(yàn)組
| baseline | modified | commit | link |
|---|---|---|---|
| 2.3.0 | false | 992447f | https://github.com/yaooqinn/spark/tree/v2.3.0-based |
4 配置
4.1 硬件配置
| 機(jī)器類別 | CPU | Memory | Disk | 臺(tái)數(shù) | Services |
|---|---|---|---|---|---|
| 虛擬機(jī) | 4 × 1 × 1 | 32g | 500g × 1 | 5 | NN(1) SNN (1) RM(1) HMS(1) SHS(1) |
| 物理機(jī) | 48 × 2 × 12 | 256g | 7.3T × 12 | 3 | DN(3) NM(3) |
| 物理機(jī) | 48 × 2× 12 | 256g | 1.1T × 1 | 4 | DN(4) NM(4) |
| 物理機(jī) | 32 × 2 × 8 | 128g | 3.6T × 12 | 1 | DN(1) NM(1) |
| 物理機(jī) | 40 × 2 × 10 | 256g | 500g × 1 | 1 | NM(1) |
| 物理機(jī) | 48 × 2 × 12 | 32g | 1.1T × 1 | 1 | DN(1) |
4.2 metrics

hdfs

yarn
4.3 SparkConf
## Basic Settings ##
spark.master yarn
spark.submit.deployMode client
spark.serializer org.apache.spark.serializer.KryoSerializer
spark.kryoserializer.buffer.max 256m
spark.local.dir ./local
## Hadoop Settings ##
spark.hadoop.fs.hdfs.impl.disable.cache true
spark.hadoop.fs.file.impl.disable.cache true
## Driver/AM Settings ##
spark.yarn.am.cores 2
spark.yarn.am.memory 2g
spark.yarn.am.memoryOverhead 512
spark.yarn.am.extraJavaOptions -XX:PermSize=1024m -XX:MaxPermSize=2048m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution
spark.driver.maxResultSize 2g
spark.driver.memory 30g
spark.driver.extraJavaOptions -XX:PermSize=1024m -XX:MaxPermSize=1024m
## Executor Settings ##
spark.executor.instances 40
spark.executor.cores 4
spark.executor.memory 20g
spark.executor.memoryOverhead 4096
spark.executor.extraJavaOptions -XX:PermSize=1024m -XX:MaxPermSize=1024m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution
## Security Settings ##
spark.yarn.keytab ?
spark.yarn.principal ?
## Dynamic Allocation Settings ##
spark.shuffle.service.enabled true
spark.dynamicAllocation.enabled false
spark.dynamicAllocation.initialExecutors 1
spark.dynamicAllocation.minExecutors 1
spark.dynamicAllocation.maxExecutors 50
## SQL Configurations ##
spark.sql.autoBroadcastJoinThreshold 204857600
spark.sql.warehouse.dir /user/spark/warehouse
# spark.sql.hive.convertCTAS true
# spark.sql.sources.default parquet
spark.sql.shuffle.partitions 1024
# spark.sql.hive.convertMetastoreParquet false
spark.sql.crossJoin.enabled=true
## History Server Client Settings ##
# spark.eventLog.enabled true
spark.eventLog.compress true
spark.eventLog.dir hdfs:///spark2-history/
spark.yarn.historyServer.address ?:18081
spark 2.3.0加上該配置
spark.sql.statistics.fallBackToHdfs true
5 測(cè)試結(jié)果
5.1 實(shí)驗(yàn)數(shù)據(jù)

實(shí)驗(yàn)數(shù)據(jù)

顯示規(guī)則
- 列1:sql statement
- 列2:參照組結(jié)果
- 列3:實(shí)驗(yàn)組結(jié)果
- 顯示規(guī)則見(jiàn)上圖
5.2 定性結(jié)果
- query19在參照組下沒(méi)跑出結(jié)果,失誤,沒(méi)記下log。
- query 77 兩組皆未出結(jié)果,
spark.driver.maxResultSize 2g設(shè)置太小 - 測(cè)試只run了一輪,所以結(jié)果并不是十分嚴(yán)謹(jǐn),[-0.1, 0.1]之間,就認(rèn)為性能相當(dāng)
- 可以看到本輪測(cè)試,實(shí)驗(yàn)組的性能相比前一輪測(cè)試有大幅度的提升,說(shuō)明諸多SQL都由SortMerge轉(zhuǎn)成了Broadcast
- 但是總體上而言,刨去“小查詢”,依然有Query 9 72 88 等感受到了明顯的下降。
- query 72 怎么又有你?還能不能玩了?
- 性能提升是應(yīng)該的,性能下降就打臉了。
6 相關(guān)分析
6.1 執(zhí)行計(jì)劃

quey 72 physical plan comparation
上圖顯示實(shí)驗(yàn)組在加上fallback參數(shù)后,邏輯計(jì)劃除了長(zhǎng)相不一樣,但邏輯結(jié)構(gòu)上已經(jīng)一致了。
6.2 Job Metics對(duì)比

參照組 Job Metrics

實(shí)驗(yàn)組 Job Metrics
- 兩輪Applications的所有Job沒(méi)有task失敗的記錄運(yùn)行良好
- Job Id 11是兩者性能的分水嶺
6.3 Stage Metrics

參照組Stage Metrics

實(shí)驗(yàn)組Stage Metrics
- 參照組的13、實(shí)驗(yàn)組的14,實(shí)為同一個(gè)Stage,主要的時(shí)差在此

參照組Stage Metrics

實(shí)驗(yàn)組Stage Metrics
- 各項(xiàng)參數(shù)基本一致或者完全一致,除了Duration這一下,實(shí)驗(yàn)組完完全全的落后

參照組 DAG

實(shí)驗(yàn)組 DAG
- 比較兩者的DAG完全一致,邏輯上沒(méi)問(wèn)題,問(wèn)題的原因就可能是對(duì)應(yīng)的物理算子,或者Spark Core的改動(dòng)產(chǎn)生的性能regression了?;蛘呤俏揖S護(hù)的分支不小心加了性能優(yōu)化特性[吃了一驚的表情]
6.4 Task Metrics

參照組 Task Id 5619

實(shí)驗(yàn)組 Task Id 5619
- 運(yùn)氣不錯(cuò) Task ID 5619正巧排序后都在第一位,可以看到性能問(wèn)題真正就是在task的執(zhí)行過(guò)程慢,也基本印證上面6.3(3)的推斷
6.5 日志分析

日志對(duì)比5619 assigned to finished 左側(cè)參照組 右側(cè)實(shí)驗(yàn)組

接上 日志對(duì)比5619 assigned to finished
- 截取5619從開(kāi)始到結(jié)束段的executor日志進(jìn)行對(duì)比
- 執(zhí)行節(jié)點(diǎn)恰好一致
- 與之并行的相關(guān)task也一致的調(diào)度與該節(jié)點(diǎn)
- shuffle service的server也一致
- 圖中紅框處,參照組Executor出現(xiàn)1分鐘左右間隔,而實(shí)驗(yàn)組Executor出現(xiàn)3分鐘左右的間隔,這時(shí)段基本可以理解為task正在吭哧吭哧的執(zhí)行。
6.6 執(zhí)行計(jì)劃 VS DAG

DAG
- 對(duì)比執(zhí)行計(jì)劃 Stage14 為最后一個(gè)SortMergeJoin的右表,對(duì)應(yīng)我們Stage 13就是在做Sort的左表(中間表)
- 所以基本可以猜測(cè)
SortExec在2.3.0有性能regression,由于跨過(guò)了2.2相關(guān)的版本,所以并不能確定引入的時(shí)間點(diǎn)。
7 總結(jié)
- 對(duì)于那些沒(méi)有Hive Statistics和Spark Statistics信息的表,需要注意在2.3.0之后
spark.sql.statistics.fallBackToHdfs true去fallback,當(dāng)然最好還是能去執(zhí)行analyze來(lái)生成。 -
SortExec物理算子應(yīng)該極有可能有性能regression,需要看代碼/PR的變更。后續(xù)有時(shí)間可以再帶點(diǎn)分享。有興趣的可以根據(jù)本文提供的線索去分析一下,如果是的話可以貢獻(xiàn)社區(qū)。
8 后記
蜀道難,還能不能玩了?