ETL vs ELT — Data Engineering

ETL vs ELT Dua pola utama dalam memindahkan data dari sumber ke tujuan. Perbedaannya terletak pada kapan transformasi dilakukan. ETL (Extract → Transform →…

ETL dan ELT adalah dua urutan untuk tiga langkah yang sama: Extract (ambil data dari sumber), Transform (bersihkan dan susun), Load (masukkan ke warehouse). Bedanya cuma di mana dan kapan langkah transform terjadi. Bayangin belanja sayur. Cara pertama: sayurnya kamu cuci dan potong di pasar, jadi yang masuk kulkas cuma potongan siap masak, kulit dan bonggolnya ditinggal. Cara kedua: semua kamu bawa pulang utuh, masuk kulkas apa adanya, lalu dipotong di dapur waktu mau masak. Besok mau masak menu lain, bahan utuhnya masih ada. Cara pertama itu ETL, cara kedua ELT. Pasarnya sumber data, kulkasnya warehouse, dapurnya mesin warehouse.

🧪 Tebakan cepat: load harian Toko Buku untuk tanggal 1 Oktober cuma INSERT INTO penjualan SELECT .... Malam itu load-nya error di tengah, jadi dijalankan ulang. Setelah jalan dua kali, Bumi Manusia di Jakarta minggu 28 September terhitung berapa buku: 2, 4, atau 6? Tebak dulu, jawabannya ada di bagian "Load yang idempoten".

Tiga langkah yang sama

Pipeline Toko Buku dari pelajaran sebelumnya, dipecah per langkah:

Langkah Artinya Di Toko Buku
Extract membaca data dari sumber SELECT pesanan satu hari dari MySQL aplikasi
Transform membersihkan dan menyusun buang baris dobel, kota NULL jadi Tidak diketahui, harga dari katalog, hitung minggu
Load menulis ke tabel tujuan INSERT ke warehouse

Pipeline biasanya jalan per hari: tiap malam, satu load harian mengambil pesanan kemarin. Di Lab, sumber dan warehouse ditaruh di satu SQLite supaya bisa dijalankan bareng. Di dunia nyata keduanya database terpisah, dan sebuah script memindahkan hasil query dari yang satu ke yang lain.

ETL: bersih dulu, baru masuk

Di ETL, transform terjadi sebelum data sampai di warehouse. Warehouse cuma menerima hasil yang sudah bersih. Load harian 1 Oktober:

INSERT INTO penjualan
SELECT DISTINCT oi.order_id, oi.book_id,
       date(o.created_at) AS tanggal,
       date(o.created_at, 'weekday 0', '-6 days') AS minggu,
       COALESCE(c.city, 'Tidak diketahui') AS kota,
       b.title AS judul,
       oi.qty,
       b.price AS harga
FROM order_items oi
JOIN orders o ON o.id = oi.order_id
JOIN customers c ON c.id = o.customer_id
JOIN books b ON b.id = oi.book_id
WHERE date(o.created_at) = '2026-10-01';

Di dunia nyata, transform ETL sering ditulis di Python (pandas, dua pelajaran lagi) dan jalan di server sendiri. Idenya sama: warehouse gak pernah melihat data mentahnya.

ELT: masuk mentah, dibersihkan di warehouse

Di ELT, extract dan load jalan duluan, apa adanya. Transform terjadi di dalam warehouse, dengan SQL:

-- 1. Extract + Load: salin baris 1 Oktober tanpa diubah
INSERT INTO raw_order_lines
SELECT oi.id, o.id, o.created_at, c.name, c.city, b.id, b.title, oi.qty, oi.price
FROM order_items oi
JOIN orders o ON o.id = oi.order_id
JOIN customers c ON c.id = o.customer_id
JOIN books b ON b.id = oi.book_id
WHERE date(o.created_at) = '2026-10-01';

-- 2. Transform: bangun ulang penjualan dari semua baris mentah
DROP TABLE IF EXISTS penjualan;
CREATE TABLE penjualan AS
SELECT DISTINCT r.order_id, r.book_id,
       date(r.created_at) AS tanggal,
       date(r.created_at, 'weekday 0', '-6 days') AS minggu,
       COALESCE(r.city, 'Tidak diketahui') AS kota,
       r.title AS judul,
       r.qty,
       b.price AS harga
FROM raw_order_lines r
JOIN books b ON b.id = r.book_id;

Di mana pembersihan terjadi

ETL ELT
Transform jalan di sebelum warehouse: query ke sumber atau script Python di dalam warehouse, pakai SQL
Yang tersimpan di warehouse hasil bersih saja data mentah, plus tabel bersih yang dibuat darinya
Aturan bersih ternyata salah extract ulang dari sumber, kalau datanya masih ada jalankan ulang SQL transform di atas raw
Butuh kolom yang dulu dibuang gak bisa: kolomnya gak pernah dimuat masih ada di raw
Tool yang sering dipakai script Python, Informatica, Talend Airbyte atau Fivetran untuk E dan L, dbt untuk T

Kenapa ELT menang

Dulu warehouse mahal dan lambat, jadi data dirapikan dulu di server lain supaya yang masuk sekecil mungkin. Warehouse cloud seperti BigQuery dan Snowflake mengubah hitungannya: storage-nya murah, dan compute-nya (tenaga hitung) bisa dibesarkan sesaat untuk satu query berat lalu dimatikan lagi. Jadi lebih murah memuat semuanya mentah dan membersihkannya dengan SQL di sana. Bonusnya: SQL dikuasai analis juga, dan data mentahnya bisa diolah ulang kapan saja. Karena itu ELT lebih tepat kalau warehouse tujuannya punya compute besar.

ETL masih dipakai kalau:

Banyak tim memakai campurannya: buang kolom sensitif di jalan, sisanya dimuat mentah lalu dibersihkan di warehouse.

Load yang idempoten

Idempoten artinya dijalankan sekali atau berkali-kali, hasil akhirnya sama (kamu sudah ketemu istilah ini di pelajaran API Idempotency). Load harian pasti suatu saat dijalankan ulang: error di tengah, server restart, atau ada yang menekan tombol "run" dua kali.

Load ETL tadi cuma INSERT. Dijalankan dua kali untuk 1 Oktober, hasilnya di SQLite:

Load 1 kali Load 2 kali
Baris 1 Oktober di penjualan 2 4
Bumi Manusia, Jakarta, minggu 28 September 2 4
Laskar Pelangi, Jakarta, minggu 28 September 3 3

Jawabannya 4. Itu jawaban tebakannya. Bumi Manusia menyalip Laskar Pelangi lagi, jawaban salah yang sama dengan pelajaran sebelumnya, kali ini gara-gara pipeline sendiri. Warehouse gak menolak: BigQuery dan Snowflake memang gak memaksakan primary key, jadi baris kembar masuk diam-diam.

Cara paling umum supaya idempoten: hapus dulu bagian yang mau diisi, baru isi. Bagian itu disebut partisi, di sini satu tanggal:

BEGIN;
DELETE FROM penjualan WHERE tanggal = '2026-10-01';
INSERT INTO penjualan
SELECT DISTINCT oi.order_id, oi.book_id,
       date(o.created_at) AS tanggal,
       date(o.created_at, 'weekday 0', '-6 days') AS minggu,
       COALESCE(c.city, 'Tidak diketahui') AS kota,
       b.title AS judul,
       oi.qty,
       b.price AS harga
FROM order_items oi
JOIN orders o ON o.id = oi.order_id
JOIN customers c ON c.id = o.customer_id
JOIN books b ON b.id = oi.book_id
WHERE date(o.created_at) = '2026-10-01';
COMMIT;

Cara kedua: upsert, tulis kalau belum ada, ubah kalau sudah ada, berdasarkan kunci. Di SQLite dan PostgreSQL INSERT ... ON CONFLICT (order_id, book_id) DO UPDATE SET ..., di MySQL INSERT ... ON DUPLICATE KEY UPDATE, di BigQuery dan Snowflake MERGE. Di ELT, load ke raw juga harus idempoten: diulang tanpa DELETE, raw_order_lines jadi 22 baris. Jawaban di penjualan kebetulan tetap benar karena DISTINCT membuang baris kembar, tapi raw-nya sudah gak cocok dengan sumber.

⚠️ Jebakan yang sering ketemu

TL;DR: ETL dan ELT adalah tiga langkah yang sama, Extract, Transform, Load, dengan urutan beda. ETL membersihkan data sebelum masuk warehouse, jadi warehouse cuma menyimpan hasil bersih. ELT memuat data mentah ke tabel raw, lalu membersihkannya dengan SQL di dalam warehouse; ini pola utama sekarang karena compute warehouse cloud murah dan bisa dibesarkan, dan raw-nya bisa diolah ulang. ETL masih dipakai untuk data sensitif yang gak boleh masuk warehouse. Load harus idempoten: INSERT saja yang diulang bikin 1 Oktober jadi 4 baris dan Bumi Manusia jadi 4; DELETE per tanggal lalu INSERT dalam satu transaksi (atau upsert) membuat hasilnya tetap 2 baris, berapa kali pun dijalankan.

Yang akan kamu pelajari