Type something to search...
Membangun ETL Pipeline yang Scalable dengan AWS Glue (CSV ke Parquet + Partitioning)

Membangun ETL Pipeline yang Scalable dengan AWS Glue (CSV ke Parquet + Partitioning)

AWS Glue ETL Data Engineering

Kenapa Aku Mulai Belajar AWS Glue

Di pekerjaanku sekarang, aku bekerja dengan data dalam skala yang belum pernah aku tangani sebelumnya: kita bicara tentang terabyte, dan datanya terus masuk setiap hari. Aku nggak bisa cerita detail, tapi industri ini memang menghasilkan data yang sangat banyak, dan menjaga agar data tetap bisa di-query dan terkelola adalah tantangan engineering yang nyata.

Pengalaman itu mendorongku untuk lebih mendalami bagaimana pipeline data skala besar sebenarnya dibangun. AWS Glue terus muncul sebagai tools utama untuk pekerjaan ini, jadi aku memutuskan untuk benar-benar duduk dan membangun sesuatu dari awal: bukan cuma baca dokumentasi.

Aku membuat pipeline menggunakan dataset penjualan dari Kaggle (Chocolate Sales Dataset 2023-2024) untuk mereplikasi pola-pola yang aku lihat di pekerjaan dalam konteks yang lebih sederhana dan bisa dibagikan. Postingan ini adalah walkthrough-nya.


Arsitekturnya

Idenya cukup sederhana: ambil file CSV mentah, proses ke format yang lebih ramah query, dan buat bisa diakses lewat Athena. Alurnya seperti ini:

graph LR
    A[S3 raw CSV] --> B[Glue Crawler]
    B --> C[Data Catalog]
    C --> D[Glue Job PySpark]
    D --> E[S3 Parquet]
    E --> F[Athena]

Nggak groundbreaking, tapi ini pola yang akan kamu temukan di setup data lake sungguhan.


Step 1: Masukin Data Mentah ke S3

Pertama: upload file CSV ke S3. Aku menjaga struktur folder tetap bersih dari awal karena aku belajar awal-awal bahwa layout S3-mu itu pada dasarnya adalah model datamu. Kalau berantakan dari awal, semuanya di downstream ikut berantakan.

raw/
├── sales/
├── products/
├── stores/
├── customers/
└── calendar/

Setiap folder berisi satu file CSV. Simple. Satu folder, satu schema, jangan campur file dengan struktur berbeda di folder yang sama. Glue Crawler bakal berterima kasih.


Step 2: Biarkan Glue Crawler Menentukan Schema-nya

Daripada mendefinisikan semuanya manual dari awal, aku membiarkan Glue Crawler memindai folder S3 dan auto-detect schema-nya. Butuh beberapa menit untuk jalan, dan mendaftarkan semua tabel ke Data Catalog.

Konfigurasi Crawler-ku:

  • Data source: s3://<bucket>/raw/
  • Crawl subfolders: yes
  • Database: choco_db
  • Table prefix: raw_

Setelah crawl, aku dapat tabel-tabel ini:

raw_sales
raw_products
raw_stores
raw_customers
raw_calendar

Ini membuat data mentah langsung bisa di-query lewat Athena, yang berguna untuk sanity-check sebelum transformasi.

Satu hal yang aku sadari: Crawler kadang salah menentukan tipe data, terutama untuk kolom yang terlihat seperti angka tapi sebenarnya ID, atau untuk kolom tanggal. Worth double-check sebelum mengandalkan schema yang di-infer untuk sesuatu yang serius.


Step 3: ETL yang Sebenarnya: PySpark di Glue

Ini bagian intinya. Glue Job membaca dari Data Catalog, melakukan beberapa transformasi ringan, dan menulis kembali ke S3 dalam format Parquet dengan partitioning berdasarkan tahun dan bulan.

Kodenya lebih bersih dari yang aku harapkan untuk PySpark:

from awsglue.context import GlueContext
from pyspark.context import SparkContext
from pyspark.sql.functions import col, to_date, year, month
sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
# Baca dari Data Catalog
datasource = glueContext.create_dynamic_frame.from_catalog(
database="choco_db",
table_name="raw_sales"
)
df = datasource.toDF()
# Parse tanggal dan ekstrak kolom partisi
df = df.withColumn("order_date", to_date(col("order_date"), "yyyy-MM-dd"))
df = df.withColumn("year", year(col("order_date")))
df = df.withColumn("month", month(col("order_date")))
# Tulis sebagai Parquet ter-partisi
df.write \
.mode("overwrite") \
.partitionBy("year", "month") \
.parquet("s3://<your-bucket>/processed/sales_parquet/")

Baris .partitionBy("year", "month") yang melakukan sebagian besar pekerjaan di sini. Glue (melalui Spark di bawahnya) secara otomatis mengorganisir output ke dalam subfolder berdasarkan nilai kolom tersebut.


Step 4: Tampilan Output di S3

Setelah job selesai, struktur folder di S3 menjadi:

processed/sales_parquet/
├── year=2023/
│ ├── month=1/
│ ├── month=2/
│ └── ...
├── year=2024/

Inilah yang membuat partitioning sangat berguna. Saat kamu query “kasih semua penjualan Januari 2023,” Athena tidak scan seluruh dataset. Dia hanya baca folder year=2023/month=1/. Untuk dataset besar, ini bisa memangkas waktu dan biaya query secara signifikan.

Ini salah satu hal yang terlihat jelas kalau dipikir belakangan tapi gampang kelewatan saat baru mulai di data engineering.


Step 5: Mendefinisikan Schema Manual di Athena

Meskipun Crawler bisa detect schema, aku lebih prefer mendefinisikannya manual untuk tabel yang sudah diproses. Ini memberi kontrol eksplisit, menghindari kejutan mismatch tipe data, dan membuat tabel lebih mudah didokumentasi.

CREATE EXTERNAL TABLE processed_sales_parquet (
order_id STRING,
order_date DATE,
product_id STRING,
store_id STRING,
customer_id STRING,
quantity BIGINT,
unit_price DOUBLE,
discount DOUBLE,
revenue DOUBLE,
cost DOUBLE,
profit DOUBLE
)
PARTITIONED BY (
year INT,
month INT
)
STORED AS PARQUET
LOCATION 's3://<your-bucket>/processed/sales_parquet/';

Lalu jalankan ini agar Athena mengenali partisi yang sudah ada:

MSCK REPAIR TABLE processed_sales_parquet;

Tanpa itu, Athena melihat tabel kosong padahal datanya sudah ada di S3.


Step 6: Query dengan Athena

Cek count dasar untuk konfirmasi semuanya ter-load dengan benar:

SELECT COUNT(*) FROM processed_sales_parquet;

Lalu query yang partition-aware untuk verifikasi filtering benar-benar bekerja:

SELECT COUNT(*)
FROM processed_sales_parquet
WHERE year = 2023 AND month = 1;

Kalau kedua query ini memberikan angka berbeda, partitioning sudah bekerja.


Yang Aku Ambil dari Ini

Auto schema detection itu berguna tapi rapil. Crawler bagus untuk eksplorasi data baru dengan cepat, tapi aku nggak akan mengandalkannya untuk schema production. Dia cenderung meng-infer kolom partisi sebagai string padahal harusnya integer, yang merusak partition pruning.

Struktur folder S3-mu adalah strategi query-mu. Aku nggak sepenuhnya menghargai ini sampai aku melihat seberapa langsung dampaknya ke performa query. Pikirkan bagaimana kamu akan men-query data sebelum memutuskan cara mempartisinya.

Parquet itu game changer. Aku tahu Parquet lebih baik dari CSV untuk analytics, tapi melihatnya langsung di praktek — query lebih cepat dan footprint storage lebih kecil — bikin terasa lebih nyata. Kalau kamu membangun sesuatu yang analytics-related, benar-benar nggak ada alasan untuk tetap di CSV.

Glue Jobs itu mahal kalau nggak dikonfigurasi dengan benar. DPU cepat numpuk. Untuk project kecil ini OK, tapi di workload sungguhan kamu perlu tune jumlah worker dan pertimbangkan apakah pakai G.1X atau G.2X tergantung job-nya.


Selanjutnya

Ini baru fondasi. Bagian yang menarik datang berikutnya: join kelima tabel — sales, products, customers, stores, calendar — untuk membangun dataset analytics yang properly enriched. Di situlah kamu mulai masuk ke model yang benar-benar bisa powering dashboard atau feeding ke pipeline machine learning.

Akan aku tulis di postingan berikutnya.


Repository

Tambahkan link repository GitHub-mu di sini

Share:

Related Posts