Data Skew: Beginner
What Skew Is
You can now define data skew precisely: partitions of wildly unequal size, minted by a shuffle that groups rows by key.
A property of the data, not the code
- Every partition holds a similar share of rows
- Every task does similar work
- Tasks finish together; the stage ends
- Doubling executors roughly halves the time
- One partition holds a huge share of rows
- One task does most of the work
- The stage waits for its biggest partition
- Extra executors just wait too
The Straggler Task
You can now recognize a straggler task as the signature symptom of skew, and know what it is doing to your schedule.
What the straggler costs you
Where Hot Keys Come From
You can now predict which keys in your own tables will run hot before you ever run the job.
| Key you shuffle on | The likely hot value | Why it is hot |
|---|---|---|
| customer_id | Your biggest enterprise account | A few whales generate most of the events |
| country / region | The home market | One geography dominates the user base |
| product_id | The bestseller, or a default SKU | Hits follow a power law |
| event_type | page_view or heartbeat | High-volume telemetry drowns rare events |
| any nullable column | NULL itself | Every missing value collects into one bucket |
Reading your own schema for heat
Spotting Skew in the UI
You can now confirm skew in the Spark UI by reading a stage's max-versus-median task metrics.
| Summary metric | Healthy stage | Skewed stage |
|---|---|---|
| Duration: max vs median | Within 2-3x | 10x or more |
| Shuffle read: max vs median | Roughly even | One task reads many times the median |
| Records: max vs median | Roughly even | One task processes most of the rows |
| Failures | None | Often none; sometimes the max task OOMs |
From symptom to key
Why Skew Wastes the Cluster
You can now explain why one hot partition idles every other executor, runs up the bill, and resists more hardware.
The shape of the fix
A stage runs 200 tasks: 199 finish in 40 seconds, one runs for an hour, and the UI shows that task read 60x the median shuffle read. Your teammate proposes doubling the executor count. What happens?
- Read a stage's max task against its median before proposing any fix.
- Confirm skew with data volume (shuffle read, records), not duration alone.
- Translate straggler time into idle core-hours when you argue for fixing it.
- Watch old jobs for creeping stragglers; skew arrives with data drift, not code changes.
- Don't trust a stage's task-count progress bar; tasks are equal counts, not equal work.
- Don't add executors to cure a straggler; one partition still runs on one core.
- Don't assume a slow task means skew before checking its input size; slow nodes mimic it.
- Don't ignore a straggler that still finishes; its endgame is an OOM that never does.
> The nightly revenue rollup that has finished by 6am for a year starts landing at 7:30, and this morning it missed its SLA outright. There are no errors in the logs; every run eventually succeeds. The only change anyone can name is that the company signed its largest-ever customer last quarter.
One partition gets the pile. The whole cluster waits on it.
- Category
- Spark
- Difficulty
- beginner
- Duration
- 12 minutes
- Challenges
- 14 hands-on challenges
Topics covered: What Skew Is, The Straggler Task, Where Hot Keys Come From, Spotting Skew in the UI, Why Skew Wastes the Cluster
Lesson Sections
- What Skew Is (concepts: paDataSkew)
Everything Spark does is built on an assumption so quiet you may never have said it out loud: that the data is divided evenly. A job's data is split into partitions, one task processes each partition, and the tasks run in parallel across the cluster. When every partition holds roughly the same number of rows, every task does roughly the same amount of work and finishes at roughly the same time. That is the happy case all the parallelism math assumes. Data skew is the name for the case where the
- The Straggler Task (concepts: paDataSkew)
Skew announces itself with one unmistakable shape: the straggler. A stage launches 200 tasks. In the first half minute, 199 of them finish. The last one keeps running, for 10 minutes, for 45, sometimes for hours, while the stage progress bar sits one tick from complete. Nothing errors. Nothing retries. The job is not stuck in any way a health check can see; it is simply one task working through a partition many times bigger than everyone else's. If you spend time around production Spark, you wil
- Where Hot Keys Come From (concepts: paDataSkew)
Behind almost every straggler is a hot key: one value of the grouping or join column that owns a wildly outsized share of the rows. Real-world data is not uniform, it is top-heavy. One enterprise customer generates a third of your events. One country dominates your user base. One SKU is the product everyone buys. One referrer sends most of your traffic. When you shuffle on that column, every row carrying the hot value is delivered to the same partition, because landing same-key rows together is
- Spotting Skew in the UI (concepts: paDataSkew)
The Spark UI settles the question of whether a slow stage is skewed, and it does it with one comparison: the maximum task against the median task. Open the application UI, go to the Stages tab, and sort by duration to find the stage eating the time. Click into that stage and find the Summary Metrics table. It shows the distribution of every task-level number across the stage, min, 25th percentile, median, 75th percentile, and max, for duration, input size, shuffle read, and more. That little tab
- Why Skew Wastes the Cluster (concepts: paDataSkew)
It is tempting to file one slow task under annoyance rather than emergency: the job still finishes, after all. The reason skew deserves the emergency file is arithmetic. While the straggler grinds, every other core in the cluster is idle, and you are paying for all of them. Take a modest cluster of 50 executors with 4 cores each, 200 cores total. The stage's 199 normal tasks finish in 30 seconds; the straggler runs another 44 minutes. For those 44 minutes, 199 of your 200 cores do nothing. That