Lazy Evaluation in PySpark

Spark tutorial · PySpark.in

Lazy Evaluation in PySpark

When you build pipelines in PySpark, you often chain together several transformations on a DataFrame—filtering rows, selecting columns, joining tables, grouping values and more. Unlike many Python libraries, Spark does not execute these operations right away. Instead, it records them and waits until you explicitly ask for the result. This design is known as lazy evaluation and is key to Spark’s performance and scalability.

What is Lazy Evaluation?

Lazy evaluation means that transformations on an RDD, DataFrame or Dataset build a plan rather than compute results immediately. According to Spark documentation and tutorials:

In essence, you are writing a recipe of what you want to do, but Spark only cooks when you call an action.

How Lazy Evaluation Works

  1. Record transformations: Each time you apply a transformation like filter() or groupBy(), Spark adds a node to the DAG. The data itself remains untouched; Spark simply notes what should happen.
  2. Optimise the plan: Because nothing has executed yet, Spark can analyse the DAG, combine adjacent operations, and remove unnecessary steps. This optimisation reduces the number of passes over the data
  3. Trigger execution with an action: The first action—such as show() or count()—triggers Spark to traverse the DAG from the beginning, launch tasks across the cluster and compute the result. Spark only reads the data partitions required for that result; for example, if you call first(), Spark may read only the first partition and ignore the rest

Why Lazy Evaluation is Beneficial

Lazy evaluation offers several practical advantages:

Example: Watching Lazy Evaluation in Action

Let’s see lazy evaluation in practice. In this example we load a CSV, apply several transformations and call an action at the end. Note that nothing happens until show() is executed:

```

from pyspark.sql import SparkSession

 

# Start a SparkSession

def create_spark_session():

    return SparkSession.builder.appName("LazyEvalDemo").getOrCreate()

 

spark = create_spark_session()

# Load a CSV file (replace with your path)

df = spark.read.csv("s3a://pyspark420/uploads/b0cbebc8-4e6f-4544-95be-d7702f864d14.csv", header=True, inferSchema=True)

# Transformations: build the plan

high_salary = df.filter(df.salary > 60000)     # filter rows

selected = high_salary.select("name", "salary")  # select columns

sorted_df = selected.orderBy("salary", ascending=False)  # sort

# At this point, Spark hasn't read the file or filtered anything!

# Action: triggers execution

sorted_df.show(3) 

```

# Now Spark will read, filter, select and sort the data, then display the top 3 records.

The call to show(3) starts the computation. If we replace show(3) with first(), Spark may only read enough partitions to return the first row, leaving the rest of the dataset untouched.

Viewing the DAG and Execution Plan

You can inspect the DAG and understand how Spark plans to run your code. Use the explain() method on a DataFrame to see the logical and physical plans,) to view a graphical DAG:

# Explain the plan

PLAINTEXT
1sorted_df.explain("formatted")
▶ Output will appear here.

# This prints the logical and physical plan, showing how Spark will perform the filter, select and sort operations.

In the Spark UI, each operation appears as a node. Stages are separated by shuffle boundaries, and tasks within a stage can run in parallel.The following infographic summarises lazy evaluation: transformations are queued up and execution begins only when an action is called.

Working with Lazy Evaluation

More Spark tutorials

All tutorials · Try the free PySpark compiler · Practice challenges