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

Spark DataFrame 與 SQL:把更多資訊交給 Optimizer

理解 schema、logical plan、Catalyst 與 columnar execution,為何常比 opaque RDD code 更有效率。

RDD 告訴 Spark 如何轉換 object;DataFrame 還告訴 Spark column 與 type 代表什麼。多出來的 structure 讓 engine 能 rewrite logical plan、prune columns、push filters,並選 physical operators。

用三層讀 execution plan

  1. Parsed logical plan 對應原始 query。
  2. Optimized logical plan 套用等價 rewrite。
  3. Physical plan 選 scan、exchange、join 與 aggregation algorithm。

不要先猜,先跑 explain()。檢查 full scan、不必要的 Exchange、sort,以及和真實資料差太多的 estimated size。

少選 column、提早 filter

Column pruning 讓 columnar format 不必讀 unused fields。Predicate pushdown 讓 Parquet 等 source 跳過無關 row groups。前提是 expression 必須能被 engine 理解;opaque Python UDF 常阻擋 optimization,也增加 serialization overhead。

Join 決定資料搬到哪裡

Small table 可以 broadcast 到 executors,避免 large side shuffle。Large-large join 通常要依 key repartition。錯誤 size estimate 可能選錯 strategy;skew 則會讓單一 reduce partition 過載。

result = (
    orders.filter("status = 'paid'")
          .select("customer_id", "amount")
          .join(customers.select("customer_id", "country"), "customer_id")
          .groupBy("country").sum("amount")
)
result.explain("formatted")

白話來說: Higher-level API 常更快,不只是 SQL 比較短,而是 Spark 看得懂並能重新安排工作。

複習卡

  • Schema 給 optimizer semantic information。
  • Logical plan 描述意義;physical plan 描述執行。
  • Projection/predicate pushdown 減少 I/O。
  • UDF 可能把工作藏在 Catalyst 看不到的地方。
  • Join strategy 很大程度是 data movement decision。