Partitioning & Bucketing in PySpark โ Optimize Large Dataset Performance
At NeoMart, the data team works with billions of rows every day:
- Sales records by date and region
- Clickstream events by user and session
- Product catalogs across multiple categories
Reading all data every time is slow and expensive.
Partitioning and bucketing let Spark skip irrelevant data and reduce shuffle during joins and aggregations.
1. Understanding Partitioningโ
Partitioning physically splits data into directories based on column values.
- Each partition = a subdirectory
- Example: partition by
yearorregion - Spark can prune partitions during queries
Example Datasetโ
data = [
("2025-01-01", "Electronics", 12000),
("2025-01-01", "Grocery", 4000),
("2025-02-01", "Electronics", 15000),
("2025-02-01", "Fashion", 3000)
]
df = spark.createDataFrame(data, ["date", "category", "revenue"])
2. Writing Partitioned Dataโ
df.write.mode("overwrite") \
.partitionBy("category") \
.parquet("/tmp/neo_partitioned")
-
Creates a folder for each category:
/tmp/neo_partitioned/category=Electronics/
/tmp/neo_partitioned/category=Grocery/ -
Querying
category='Electronics'reads only that partition.
3. Reading Partitioned Dataโ
df_read = spark.read.parquet("/tmp/neo_partitioned/category=Electronics")
df_read.show()
Outputโ
| date | category | revenue |
|---|---|---|
| 2025-01-01 | Electronics | 12000 |
| 2025-02-01 | Electronics | 15000 |
Partition pruning reduces I/O and speeds up queries.
4. Partitioning Best Practicesโ
โ Partition by high-cardinality but selective columns (like date, region)
โ Avoid partitioning by too many columns โ too many small files
โ Keep less than 1000 partitions per table for efficiency
โ Combine with predicate filtering for query speed
5. Understanding Bucketingโ
Bucketing divides data into fixed buckets using a hash function on a column.
- Unlike partitioning, bucketed data is in files within the same folder
- Useful for joins, aggregations, sampling
- Bucketing enables co-located joins โ no shuffle
6. Writing Bucketed Tablesโ
df.write.mode("overwrite") \
.bucketBy(4, "category") \
.sortBy("revenue") \
.saveAsTable("bucketed_sales")
- 4 buckets for
category - Within each bucket, data sorted by
revenue
7. Reading & Joining Bucketed Tablesโ
bucketed_df = spark.table("bucketed_sales")
# Optimized join with another bucketed table
other_df = spark.table("bucketed_sales")
joined_df = bucketed_df.join(other_df, "category")
- Spark can perform bucketed joins โ avoids full shuffle
- Great for large fact-dimension joins