Based on the MLS-C01 exam guideReport an error
Last week we covered "where and how to bring the data in" (ingestion and storage). Now comes the stage where you turn that raw data into a form the model can consume. On MLS-C01, ETL is a core area that asks "which tool do you choose, at what scale, with what cost and operational burden?"
| Stage | Meaning | Example in ML |
|---|---|---|
| Extract | Pull data from the source | Reading from S3, RDS, DynamoDB, logs |
| Transform | Clean, join, aggregate, encode | Handling missing values, encoding categoricals, computing features |
| Load | Write the processed result to the destination | Saving to a training S3 bucket or a feature store |
A variant called ELT (Extract-Load-Transform) is also used these days. You load raw data into the data lake (S3) first and transform it when needed. The data lake + Athena/Spark combination is effectively an ELT pattern, and it works well when you handle large volumes of data that are less structured.
| Type of transformation | Example | Caution |
|---|---|---|
| Cleansing | Drop rows with missing values, cast types, filter logic errors | Compute statistics only from the training set |
| Join | Transaction table + customer profile | Check whether the row count blows up from a join explosion (duplicate keys) |
| Aggregation | Per-user purchase total over the last 30 days | Make the aggregation reference point explicit (future information leakage) |
| Encoding and scaling | Categorical → numeric, standardization | Use the same logic in training and inference |
| Partition rearrangement | Re-save into per-date directories | Too many partitions cause the small files problem |
AWS Glue is an Apache Spark-based ETL service where you do not manage servers yourself (serverless). AWS launches and shuts down the cluster for you, so engineers focus only on the transformation logic.
# Skeleton of a Glue PySpark ETL job
import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
args = getResolvedOptions(sys.argv, ['JOB_NAME'])
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)
# 1) Read raw data from the Data Catalog (Extract)
raw = glueContext.create_dynamic_frame.from_catalog(
database="ml_raw", table_name="clicks"
)
# 2) Transform: drop null fields + map columns (Transform)
mapped = ApplyMapping.apply(frame=raw, mappings=[
("user_id", "string", "user_id", "string"),
("ts", "string", "event_time", "timestamp"),
("amount", "string", "amount", "double"),
])
clean = DropNullFields.apply(frame=mapped)
# 3) Load into the training S3 bucket as Parquet (Load)
glueContext.write_dynamic_frame.from_options(
frame=clean,
connection_type="s3",
connection_options={"path": "s3://ml-train/clicks/"},
format="parquet"
)
job.commit()A Glue job's processing capacity is measured in DPUs (Data Processing Units). 1 DPU is roughly 4 vCPU + 16GB of memory. If a job is slow, you scale out horizontally by increasing the number of DPUs (workers), or you raise performance by using the Spark engine in a newer Glue version. You are billed only for the DPU-hours you actually use.
EMR (Elastic MapReduce) is a managed service for running big data frameworks such as Hadoop, Spark, Hive, Presto, and HBase directly on an EC2 cluster. If Glue is "Spark only, serverless, simple," EMR is the option for "multiple engines, fine-grained tuning, direct control."
Situations where EMR is advantageous:
# Create an EMR cluster (with Spark) — CLI example
aws emr create-cluster \
--name "ml-preprocess" \
--release-label emr-7.1.0 \
--applications Name=Spark \
--instance-groups \
InstanceGroupType=MASTER,InstanceCount=1,InstanceType=m5.xlarge \
InstanceGroupType=CORE,InstanceCount=4,InstanceType=m5.2xlarge \
--use-default-roles \
--auto-terminate--auto-terminate automatically shuts down the cluster when the work finishes, preventing wasted cost.| Decision axis | Leans toward Glue | Leans toward EMR |
|---|---|---|
| Operational burden | Minimal management, no dedicated staff | Fine-grained control, staff available for tuning |
| Workload nature | Short and sporadic, standard transformations | Long, heavy, recurring batches |
| Frameworks | Spark alone is enough | Hive, Presto, HBase, etc. used alongside |
| Cost structure | Only the DPU-hours used | Large savings possible with Spot |
| Startup latency | Fast per job | Cluster startup time needed |
| Catalog | Native integration | Connect the Glue Catalog as the metastore |
The Glue vs EMR choice is within exam scope. The decision criteria are (1) Operational burden: minimal management → Glue, fine-grained control → EMR. (2) Workload nature: short and sporadic → Glue, long and heavy recurring batches → EMR. (3) Framework variety: if it is Spark only, Glue is enough; if you need multiple engines, EMR.
Once data exceeds a few terabytes, "how you store and read it efficiently" matters as much as "how you transform it."
s3://bucket/year=2026/month=06/, Spark/Athena skips unnecessary data (partition pruning).# Efficient read in Spark using partition + column pruning
df = (spark.read.parquet("s3://ml-train/clicks/")
.filter("year = 2026 AND month = 6") # partition pruning
.select("user_id", "event_time", "amount")) # column pruning[Inefficient] CSV · no partitions · 1 million small files
→ full scan + per-file overhead → job time and cost explode
[Efficient] Parquet · dt/region partitions · 256MB per file
→ reads only the needed partitions and columns → scan volume is a fraction (tens of times smaller)
⚠️ Pitfall: "The data is big, so let's just spin up a big EMR cluster" is a common wrong-answer lure. If the work is sporadic and operations staff is small, running a big EMR cluster around the clock is inefficient in both cost and management. In that case Glue or EMR Serverless is more suitable.
⚠️ Pitfall: It is easy to think the finer the partitions the better, but if every partition produces small files, things actually get slower. Design the partition count and the file size together.
Whether it is Glue or EMR, what runs inside is Spark. To read performance-problem scenarios you need at least a basic picture.
Driver ──split work──▶ Executor × N
· builds the job plan · does the actual computation per partition
· collects results · caches intermediate results in memory
▲ │
└──────── shuffle: redistributing data across nodes ────┘
groupBy or join, data moves between nodes. It is the most expensive operation.write, count) is called."The job is slow → make the instances bigger" is not always the answer. If the shuffle is the bottleneck, changing the join strategy (broadcasting the small table) or spreading out the skewed key is more effective.
Preprocessing results ultimately flow into SageMaker training. AWS provides several paths that connect transformation to training.
SageMaker Processing and Glue seem to overlap in role, but they have a different character. Glue is strong at ETL across the data lake (producing cleansed data shared by multiple consumers), while SageMaker Processing integrates naturally with preprocessing tied to a specific ML job (feature generation for this model only).
Tomorrow we look at the training data pipeline that automates these transformation jobs with Step Functions and SageMaker Pipelines instead of running them by hand each time.
Click a choice to reveal the answer and explanation.
Question 1
A team with little operations staff needs to handle standard Spark transformation jobs that occur sporadically a few times a day. What minimizes the burden of launching and managing clusters yourself?
Question 2
You process petabyte-scale data for long periods, use Hive and Presto in addition to Spark, and need to fine-tune instance types and memory. Which service is most suitable?
Question 3
When reading large-scale training data stored in S3 with Spark, which combination of storage strategies most effectively reduces scan cost and I/O?
Question 4
In AWS Glue, which component scans data in S3, infers the schema automatically, and registers it as a table in the central metadata store?
Question 5
In an ML pipeline, when distinguishing between "producing shared cleansed data across the data lake" and "preprocessing for one specific model only," which pairing of tools is generally the more suitable?