STRUCTURED APISPySpark

Joins in Spark

Distributed data processing with Spark — pick a topic on the left and its full breakdown loads here: the execution model, worked jobs and diagrams, performance and shuffle behavior, and the habits that keep Spark jobs fast, correct, and affordable.

18 min readTopics chapter readerLevel · Structured APIs
01 · Orientation

What You'll Master Here

A join gathers matching keys together. By default that means shuffling both sides (slow). If one side is small, you can instead copy it to every executor (a broadcast join) and skip the shuffle entirely.

4 min · Topic 1 of 6

Joins combine two DataFrames on a key, and they are both essential and the most common place Spark jobs go slow. This chapter covers the join types you will use, how Spark physically executes a join (the strategies), the single biggest optimization (the broadcast join), and the pitfalls that turn a join into a runaway job.

The key realisation: a normal join is a wide transformation. It shuffles both sides of the data across the cluster so matching keys land together, exactly the expensive operation from Chapter 5. Most join tuning is about avoiding or shrinking that shuffle.

Everything is concrete: two small tables joined every which way, with inputs and outputs, plus diagrams of the shuffle join and the broadcast join.

Core mental model

A join gathers matching keys together. By default that means shuffling both sides (slow). If one side is small, you can instead copy it to every executor (a broadcast join) and skip the shuffle entirely.

Why it matters

"My Spark job is slow" is, more often than not, a join problem, a huge shuffle, a skewed key, or a missed broadcast. Joins are also a staple of interviews. Getting them right is core competence.

join key
The column(s) two DataFrames are matched on.
join type
Which rows survive: inner, left/right/full outer, left semi, left anti.
shuffle join
The default: both sides are shuffled by key so matches meet (wide, slow).
broadcast join
Copy a small table to every executor and join locally, no shuffle.
Common mistake

Treating every join as cheap. A default join shuffles both sides; on large data that shuffle often dominates the whole job.

Better habit

Filter and select before joining, so less data is shuffled.

Broadcast the small side whenever one table is small.

Check the join key for skew and nulls before blaming Spark.

The big idea

A join is a shuffle unless you can broadcast. Most join performance work is "shrink the data, then either broadcast the small side or fix the skewed key".

Remember this

Joins match two DataFrames on a key. By default they shuffle both sides (wide and slow); broadcasting a small side avoids the shuffle. Most slow jobs are slow joins.

Practice2 prompts
  1. Why is a default join a wide transformation?
  2. When can you avoid the join shuffle entirely?