Optimize a Slow Spark Pipeline
A critical financial aggregation pipeline takes 48 minutes to run on a 4-node Databricks cluster, burning excessive cloud DBU credits and breaching daily SLAs. Your mission is to analyze the Spark execution plan, eliminate shuffle bottlenecks, resolve extreme data skew, replace slow Python UDFs, and achieve a 10x+ speedup.
Mission & Operational Context
Understand cloud compute costs, SLA penalties, and the mechanics of Spark cluster stragglers.
The Cloud Cost Escalation
The Cloud FinOps dashboard flagged this single sales aggregation job as responsible for $4,200/month in compute spend. When looking at the Spark UI Ganglia metrics, 3 executor nodes sit at 0% CPU utilization for over 30 minutes, while 1 solitary executor core pegged at 100% CPU struggles to process a massive skewed partition.
Furthermore, the script uses a Python UDF that serializes millions of rows through Py4J, and shuffles 50 rows of store reference data into 2,000 tiny partition files. Your job as a Lead Spark Engineer is to profile, refactor, and validate this pipeline so it executes in under 3 minutes with identical results.
Starter Materials & Execution Plan
Inspect the slow Python workload, physical execution plan, and the partition skew profile.
Hands-On Optimization Workflow
Execute these systematic optimizations to dismantle the bottlenecks one by one.
Replace Python UDF with Native Catalyst Expressions
Eliminate JVM-to-Python serialization by converting tier_udf into native when() / otherwise().
Enable BroadcastHashJoin on Stores Table
Use broadcast(stores_df) to eliminate SortMergeJoin and shuffle exchanges.
Resolve Severe Key Skew with Salting or AQE
Mitigate the 17M row skew on STORE_ONLINE_01.
Tune Shuffle Partitions & Remove Eager Actions
Eliminate wasteful actions and set appropriate partition sizes.
Optimize Delta Lake File Layout
Enable Liquid Clustering or Z-ORDER on the final Gold Delta table.
Target Performance Benchmarks
Measure before and after metrics to prove tangible engineering improvement.
Target Performance Metrics
Physical Plan Transformation Comparison
| Component | Unoptimized Baseline | Optimized Implementation | Engineering Rationale |
|---|---|---|---|
| Join Strategy | SortMergeJoin (Shuffled) | BroadcastHashJoin | Eliminates cross-network shuffle of 20M rows |
| Tier Classification | BatchEvalPython (UDF) | Native when().otherwise() | Runs in WholeStageCodegen JVM bytecode |
| Shuffle Partitions | 2,000 tiny partitions | 32 partitions / AQE auto | Reduces task scheduling latency by 95% |
| Data Skew Handling | 1 core straggling (17M rows) | Key Salting / AQE Skew Join | Evenly saturates all 4 cluster nodes |
Validation Checks & Correctness Verification
Optimization is meaningless if the data is corrupted. Prove 100% numerical equality.
# 1. Assert row counts match baseline exactly
baseline_count = baseline_df.count()
optimized_count = optimized_df.count()
assert baseline_count == optimized_count, f"Row count mismatch: {baseline_count} vs {optimized_count}"
# 2. Assert zero difference across all aggregated values
diff_df = baseline_df.subtract(optimized_df)
assert diff_df.count() == 0, "Discrepancies found between baseline and optimized tables!"
print("✓ Correctness verified! Optimized pipeline output is 100% identical to baseline.")Evidence To Submit & Performance Report
Compile your benchmarking data and submit your final engineering report.
To receive grading and claim your badge, compile the following proof artifacts:
Common Mistakes To Avoid
Review these frequent pitfalls in Spark optimization.
Stretch / Bonus Objectives
Explore cutting-edge Spark optimization features.
Complete DEV-013 to Earn 800 XP & Spark Performance Engineer Badge
Profile the slow workload, apply targeted Spark optimizations, prove 10x+ speedup with 100% numerical equality, and submit your report.