Membangun ETL Pipeline yang Scalable dengan AWS Glue (CSV ke Parquet + Partitioning)
- Habib Abdurrasyid
- 08 Apr, 2026
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_salesraw_productsraw_storesraw_customersraw_calendarIni 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 GlueContextfrom pyspark.context import SparkContextfrom pyspark.sql.functions import col, to_date, year, month
sc = SparkContext()glueContext = GlueContext(sc)spark = glueContext.spark_session
# Baca dari Data Catalogdatasource = glueContext.create_dynamic_frame.from_catalog( database="choco_db", table_name="raw_sales")
df = datasource.toDF()
# Parse tanggal dan ekstrak kolom partisidf = 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-partisidf.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 PARQUETLOCATION '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_parquetWHERE 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