← 所有文章2025.10.10 · MSBD 5003 · Spark 大數據運算

Spark RDD:Lazy Execution、Lineage、Partition 與 Shuffle

從 execution model 判讀 Spark performance,而不是把 transformation 當成本機 collection method。

RDD 是切成 partitions 的 immutable distributed collection。API 看起來像 local collection programming,但 performance 取決於 partition 在哪裡、dependency 是否跨機器,以及 Spark 何時真正 materialize work。

Transformation 建 plan;action 才執行

map、filter、flatMap 是 lazy transformation,只會延伸 lineage graph。count、collect、save 等 action 才要求 scheduler 執行足夠的 graph 以產生結果。

Lineage 同時是 recovery mechanism:partition 遺失時,Spark 可從 ancestor recompute,不必 replicate 每個 intermediate result。

Narrow 與 wide dependency

Narrow dependency 的 child partition 只讀少量 parent partitions,通常能在同一 stage pipeline。Wide dependency,例如 groupByKey、reduceByKey、repartition 與許多 join,會把 record 跨 network 移動並建立 shuffle boundary。

input partitions -> narrow maps -> SHUFFLE -> reduce partitions

Shuffle 會增加 serialization、network、disk spill、sorting 與 straggler risk。能在 map side combine 時,reduceByKey 通常比把所有 values 都送進 groupByKey 合理。

Partition 是 parallel work 的單位

Partition 太少會讓 executor 閒置;太多則造成 scheduler overhead 與 tiny tasks。Skew 更麻煩:一個 hot key 就可能讓單一 task 拖住整個 job。要看 task duration 與 input size distribution,不能只看平均值。

只 cache 會重複使用、且 recompute 昂貴的資料。全部 cache 會吃掉 memory、讓有用 block spill,反而更慢。collect() 會把所有資料拉到 driver,只有 result 明確很小時才能使用。

白話來說: Computation 留在均衡 partitions 附近時 Spark 才快;資料必須跨 cluster 重新分組時,成本就上來了。

複習卡

  • RDD immutable、partitioned,靠 lineage recovery。
  • Transformation lazy;action trigger execution。
  • Wide dependency 形成 shuffle boundary。
  • Partition count 與 skew 決定真正 parallelism。
  • 只 persist 重複使用且 recomputation 昂貴的 lineage。