Lazy Evaluation: Transformations vs Actions in Spark
Why nothing runs until you call an action, how Spark builds a plan, and the mistakes that make a job compute the same data twice.
Apache SparkBeginner2 min readUpdated 11 Oct 2026
Two kinds of operations
| Transformations (lazy) | Actions (run the job) |
|---|---|
select, filter, withColumn, join, groupBy, union | count, collect, show, write, take |
| Return a new DataFrame | Return a result or write data |
df = spark.read.parquet("s3://lake/orders/") # nothing read yet
paid = df.filter("status = 'paid'").select("store_id", "amount") # still nothing
paid.write.parquet("s3://lake/paid/") # NOW Spark plans and runsWhy lazy?
Spark sees the whole chain before running it, so the optimizer (Catalyst) can:
- push the
filterdown into the Parquet scan, reading fewer rows - read only the columns you
select(column pruning) - combine several steps into one stage
The double-compute trap
Every action recomputes the plan from the source.
clean = expensive_cleaning(raw)
print(clean.count()) # computes clean
clean.write.parquet(out) # computes clean AGAINIf a DataFrame is used by more than one action, cache it, and release it afterwards:
clean = expensive_cleaning(raw).cache()
clean.count() # materialises the cache
clean.write.parquet(out)
clean.unpersist()See the plan
paid.explain(mode="formatted")Look for PushedFilters in the scan node. It confirms the filter reached the file reader.
Finished this note?
Related notes
PySpark DataFrame Basics in 10 Operations
pyspark · 2 min
Spark Partitions and File Sizes: repartition, coalesce and the Small-Files Problem
apache-spark · 2 min
Airflow Core Concepts: DAGs, Tasks, Operators and Runs
apache-airflow · 2 min
Normalization in Plain English: 1NF, 2NF, 3NF
data-modeling · 2 min
