Skip to main content

Is Spark overkill for datasets under 1 TB?

Summary

  • Data size alone doesn't settle it. The deciding questions are whether the data and its intermediate results fit in one machine's memory, whether the workload includes streaming, how many jobs share the data, and how much it will grow.
  • When one machine can hold the whole job, a single-node tool avoids running a cluster. DuckDB runs embedded inside a host process with no database server to install, and Polars splits work across the CPU cores of the machine it runs on.
  • Spark is a reasonable choice below a terabyte when joins or aggregations exceed one machine, when batch and streaming jobs share code, or when the same pipeline has to keep running as volume grows.
  • Spark can run small. Local mode uses one machine, and Adaptive Query Execution, on by default since Spark 3.2.0, coalesces post-shuffle partitions so you don't have to tune the default of 200 shuffle partitions to your dataset.
  • On Databricks, single node compute is intended for jobs that use small amounts of data, and serverless compute allocates and manages resources for you.

Is Spark overkill for datasets under 1 TB?

Not by size alone. A dataset under 1 TB can still exceed one machine's memory once joins, aggregations and intermediate results are counted, and it may arrive as a stream or keep growing. If a single machine can hold the whole job and will keep holding it, an in-process engine or a single-node DataFrame library avoids the coordination a distributed engine carries. If the job doesn't fit on one machine, mixes batch and streaming, or feeds shared production tables, Spark is a reasonable choice at this size.

Where Spark's overhead comes from

Spark applications "run as independent sets of processes on a cluster, coordinated by the SparkContext object in your main program," and the driver sends tasks to executors on worker nodes. That design lets Spark split one job across many machines. It also has costs that a single-process tool doesn't pay:

  • Shuffles. Operations such as repartition, groupByKey, reduceByKey and join can cause a shuffle, which "typically involves copying data across executors and machines." The Spark docs call it "an expensive operation since it involves disk I/O, data serialization, and network I/O."
  • Partition counts. spark.sql.shuffle.partitions sets the number of partitions used when shuffling data for joins or aggregations, and its default is 200. Adaptive Query Execution (AQE), enabled by default since Spark 3.2.0, coalesces post-shuffle partitions at runtime based on map output statistics, so you don't need to set a partition number that fits your dataset.

Signals that point one way or the other

Workload signal Leans toward Why
Data and intermediate results fit in one machine's memory, and will keep fitting A single-node engine such as DuckDB or Polars No cluster to run; DuckDB runs "completely embedded within a host process"
Data exceeds memory, but one machine's disk and cores are enough A single-node engine with out-of-core execution, such as Polars' streaming API It processes results "without requiring all your data to be in memory at the same time"
Joins or aggregations exceed one machine's memory or cores Spark on a cluster Executors on several nodes share the work
pandas code that has outgrown one machine pandas API on Spark pandas-style syntax that "is scalable to multiple machines in a cluster"
Continuous or incremental ingestion Spark Structured Streaming The same DataFrame API as batch, with exactly-once guarantees through checkpointing and write-ahead logs
Volume expected to grow Spark The same application runs in local mode or on a cluster, because spark-submit uses every cluster manager "through a uniform interface"

If you run Spark on small data

Start in local mode and let AQE size the shuffles. Both AQE settings below already default to true; they're set here so the intent is explicit.

from pyspark.sql import SparkSession

spark = (
    SparkSession.builder
    .master("local[*]")  # one machine, all logical cores
    .config("spark.sql.adaptive.enabled", "true")
    .config("spark.sql.adaptive.coalescePartitions.enabled", "true")
    .getOrCreate()
)

For pandas code that needs to scale out, pandas API on Spark keeps pandas-style syntax:

import pyspark.pandas as ps

psdf = ps.read_parquet("/data/events")
psdf.groupby("event_type").sum().head(3)

How Databricks approaches small and mid-size Spark jobs

Databricks docs say single node compute "is intended for jobs that use small amounts of data or non-distributed workloads such as single-node machine learning libraries," and multi-node compute "should be used for larger jobs with distributed workloads." With autoscaling, you set a minimum and a maximum number of workers, and Databricks "chooses the appropriate number of workers required to run your job." Serverless compute goes further: Databricks "automatically allocates and manages the necessary compute resources" for notebooks, Lakeflow Jobs and Lakeflow Pipelines. Photon runs Spark APIs with "no changes required" to your code, and Databricks Connect, built on Spark Connect, lets you develop in an IDE against remote compute. See compute configuration for the single node and autoscaling options.

FAQs

Can Spark run on a laptop?

Yes. Spark runs locally on one machine with Java on the system PATH or JAVA_HOME set, and the local[*] master URL uses as many worker threads as the machine has logical cores.

Which tools fit data that stays on one machine?

DuckDB is an in-process analytical database with no server to install, and Polars is a DataFrame library with a Rust core that divides work among the available CPU cores. pandas is the Python library whose API pandas API on Spark follows.

Does Spark need tuning for small datasets?

AQE handles the main setting. With spark.sql.adaptive.enabled and spark.sql.adaptive.coalescePartitions.enabled both true, the defaults, Spark picks the post-shuffle partition count at runtime once the initial number of shuffle partitions is large enough.

Is pandas API on Spark the same as pandas?

It offers "syntax that is familiar to pandas users" and runs on Spark, so it can run queries on datasets larger than memory. Import it with import pyspark.pandas as ps.

The information provided herein is for general informational purposes only and may not reflect the most current product capabilities or configurations.