ETL Pipelines in PySpark โ End-to-End Example
At DataVerse Labs, the Data Engineering team processes millions of daily transactions from various systems โ API feeds, CSV exports, app logs, and real-time streams.
To unify all this, they built a PySpark ETL pipeline that:
- Extracts data from multiple sources
- Transforms it using business rules
- Loads it into a warehouse (Snowflake/Delta/Hive)
This chapter shows you a clean, professional, end-to-end ETL pipeline you can use in any enterprise environment.
1. ETL Architecture Overviewโ
RAW DATA (CSV, JSON, DB) โ
Spark Extraction
โ
Data Cleansing & Validation
โ
Business Transformations
โ
Aggregations
โ
Data Warehouse
(Snowflake/Delta/Hive)
The pipeline we build will simulate a Retail Orders ETL Pipeline.
2. Step 1 โ Extract Phaseโ
We load CSV, JSON, and Parquet files into Spark.
Example Input Files:โ
orders.csvโ
order_id,customer_id,amount,timestamp
O1,C101,200,2024-01-01 10:00:00
O2,C102,450,2024-01-01 10:15:00
O3,C103,,2024-01-01 10:40:00
customers.jsonโ
{"customer_id": "C101", "country": "USA"}
{"customer_id": "C102", "country": "India"}
{"customer_id": "C103", "country": "UK"}
Extraction Codeโ
df_orders = spark.read \
.option("header", "true") \
.option("inferSchema", "true") \
.csv("/data/orders.csv")
df_customers = spark.read.json("/data/customers.json")
df_orders.show()
df_customers.show()
Output (orders.csv)
+--------+-----------+------+-------------------+
|order_id|customer_id|amount|timestamp |
+--------+-----------+------+-------------------+
|O1 |C101 |200 |2024-01-01 10:00:00|
|O2 |C102 |450 |2024-01-01 10:15:00|
|O3 |C103 |null |2024-01-01 10:40:00|
+--------+-----------+------+-------------------+
3. Step 2 โ Cleansing & Validationโ
3.1 Fix Null Valuesโ
from pyspark.sql.functions import col
df_orders_clean = df_orders.fillna({"amount": 0})
3.2 Validate Customer IDsโ
df_orders_valid = df_orders_clean.filter(col("customer_id").isNotNull())
4. Step 3 โ Business Transformationsโ
Join Orders with Customer Infoโ
df_joined = df_orders_valid.join(
df_customers,
on="customer_id",
how="left"
)
Add Sales Categoryโ
from pyspark.sql.functions import when
df_transformed = df_joined.withColumn(
"sales_category",
when(col("amount") > 300, "HIGH")
.when(col("amount") > 100, "MEDIUM")
.otherwise("LOW")
)
Output Exampleโ
+-----------+--------+------+-------------------+-------+--------------+
|customer_id|order_id|amount|timestamp |country|sales_category|
+-----------+--------+------+-------------------+-------+--------------+
|C101 |O1 |200 |2024-01-01 10:00:00|USA |MEDIUM |
|C102 |O2 |450 |2024-01-01 10:15:00|India |HIGH |
|C103 |O3 |0 |2024-01-01 10:40:00|UK |LOW |
+-----------+--------+------+-------------------+-------+--------------+
5. Step 4 โ Aggregation Layerโ
Daily Sales Summaryโ
from pyspark.sql.functions import to_date, sum as spark_sum
df_daily_summary = df_transformed \
.withColumn("date", to_date("timestamp")) \
.groupBy("date", "country") \
.agg(spark_sum("amount").alias("total_sales"))
Output
+----------+-------+-----------+
|date |country|total_sales|
+----------+-------+-----------+
|2024-01-01|USA |200 |
|2024-01-01|India |450 |
|2024-01-01|UK |0 |
+----------+-------+-----------+
6. Step 5 โ Load Phaseโ
You may load into:
- Snowflake
- Delta Lake
- Hive
Example: Write to Delta Lakeโ
df_transformed.write \
.format("delta") \
.mode("overwrite") \
.save("/warehouse/processed/orders")
Example: Write to Hiveโ
df_daily_summary.write \
.mode("overwrite") \
.saveAsTable("dv_dw.daily_sales")
Example: Write to Snowflakeโ
df_daily_summary.write \
.format("snowflake") \
.options(**sf_options) \
.option("dbtable", "DAILY_SALES") \
.mode("overwrite") \
.save()
7. Production-Grade ETL: Best Practicesโ
โ Use explicit schemas for large files
โ Track ETL runs with audit columns (created_at, batch_id)
โ Store raw โ cleaned โ curated layers separately
โ Use Delta Lake for versioned tables
โ Handle bad records using badRecordsPath
โ Maintain checkpoints for streaming ETL
โ Schedule ETL with Airflow, Oozie, or Databricks Jobs
Summaryโ
In this chapter, you built an end-to-end ETL pipeline in PySpark:
โ Extractionโ
- Load CSV, JSON, Parquet
โ Transformationโ
- Cleansing
- Validation
- Business rules
- Joins & nested logic
โ Loadingโ
- Delta Lake
- Hive
- Snowflake
This pipeline mirrors what real enterprise data engineering teams deploy at scale.
Next Topic โ Real Company Use Cases โ Support, Development, & Production Workflows