Apache Spark architecture: driver, cluster manager, and executors

Apache Spark

Repartition in PySparksparkhow repartition, coalesce and column-based partitioning trigger shuffles and when to use each.

1. Spark Basics

2. Spark Architecture

3. Spark Components and Libraries

4. RDDs, DataFrames, and Datasets

5. Key Transformations and Actions

6. Optimizations in Spark

Catalyst Optimizer (for SQL and DataFrames): Uses rule-based and cost-based optimization to produce efficient query plans.

Memory Management: Manages caching, shuffle files, and resource allocation for performance.


How a Spark job executes

From Action to Tasks DataFrame codelazy transformations Catalystlogical -> physical plan DAG schedulerstages at shuffles Task schedulerone task per partition Executorsrun tasks, cache Resultto driver or storage Narrow transformations (filter, select) stay in one stage; wide ones (groupBy, join) need a shuffle and start a new stage. Tuning Spark is mostly about reducing and balancing shuffles.

Nothing runs until an action such as count() or write is called. At that point the Catalyst optimizer turns the DataFrame operations into an optimised physical plan, and the DAG scheduler cuts it into stages wherever data must be redistributed across the cluster. Each stage runs one task per partition on the executors. Adaptive Query Execution (enabled by default in Spark 3.x) re-plans at stage boundaries using runtime statistics, for example coalescing small shuffle partitions or switching to a broadcast join. On Databricks, the Photon engine can execute many of these operators natively for additional speed.

Choosing an API

APIUse whenAvoid when
DataFrame / Spark SQLAlmost always: optimised by Catalyst, works in Python, SQL, ScalaYou need low-level control of partition contents
RDDCustom partition logic, unstructured records, legacy codeStructured data; you lose Catalyst optimisation
Dataset (Scala/Java)Compile-time type safety on the JVMPython (not available)
Structured StreamingIncremental processing of unbounded data with the DataFrame APIOne-off batch jobs
pandas API on SparkPorting pandas code to larger dataPerformance-critical code that needs tuned Spark idioms

Example: inspect a plan

from pyspark.sql import SparkSession, functions as F
spark = SparkSession.builder.appName("demo").getOrCreate()

orders = spark.range(1_000_000).withColumn("cust", F.col("id") % 1000)
custs  = spark.range(1000).withColumnRenamed("id", "cust").withColumn("tier", F.col("cust") % 3)

agg = (orders.join(F.broadcast(custs), "cust")      # avoid shuffling the large side
             .groupBy("tier").count())               # wide: causes a shuffle
agg.explain(mode="formatted")                        # look for Exchange and BroadcastHashJoin
print(agg.collect())

In the plan, each Exchange node is a shuffle and therefore a stage boundary. The broadcast hint ships the small table to every executor so the large table is joined without moving it.

Common pitfalls

Related: PySpark, Databricks performance, Delta Lake.