Ana içeriğe geç
Kesit SQL
Orta · Veri Mühendisliği

ETL, ELT ve veri katmanları

Ham veriden analiz tablosuna: staging, intermediate, mart.

Uygulamada aç, 7 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

ETL ve ELT

Katmanlı mimari

KatmanİçerikÖrnek
Raw / bronzeKaynaktan olduğu gibi, değiştirilmedenraw_signups
Staging / silverTemizlenmiş, tipleri düzeltilmiş, tekilleştirilmiş, adlar standartstg_signups
Mart / goldİş mantığı uygulanmış, analize hazır fact/dimensionfct_sales, dim_customer

İyi bir pipeline'ın özellikleri

Derinleş: ETL mi ELT mi, ve tekrar çalıştırılabilir yükleme

ETL ile ELT arasındaki fark yalnızca harflerin sırası değil; dönüşümün nerede ve hangi araçla yapıldığıdır. Bu, ekip yapısını, maliyeti ve hata ayıklamayı doğrudan etkiler.

ETLELT
Dönüşüm yeriAyrı bir sunucu / araçHedef ambarın içinde, SQL ile
Ham veriÇoğu zaman saklanmazBronze katmanda olduğu gibi durur
Hata sonrasıKaynaktan yeniden çekmek gerekirHam veriden yeniden dönüştürülür
Kim yazar?Entegrasyon uzmanıSQL bilen analist / analitik mühendis
Uygun olduğu yerHassas verinin ambara girmeden maskelenmesi, eski sistemlerBulut ambarları (BigQuery, Snowflake), dbt projeleri

Staging katmanında tipik temizlik

Ham raw_signups tablosunda tarihler iki biçimde geliyor: 2024-02-10 ve 29.07.2024. Staging adımı adları standartlaştırır, e-postayı normalize eder ve tarihi tek biçime çevirir:

SELECT DISTINCT
       id,
       LOWER(TRIM(email)) AS email,
       TRIM(full_name) AS full_name,
       CASE WHEN signup_date LIKE '__.__.____'
            THEN substr(signup_date, 7, 4) || '-' || substr(signup_date, 4, 2) || '-' || substr(signup_date, 1, 2)
            ELSE signup_date END AS signup_date
FROM raw_signups
ORDER BY id;

İdempotent yükleme

Bir iş gece yarısı yarıda kesildi ve yeniden başlatıldı. Yükleme INSERT ile yapılıyorsa aynı ayın satırları iki kez eklenir ve ciro iki katına çıkar. İdempotent bir adım, kaç kez çalışırsa çalışsın aynı sonucu bırakır. En basit kalıp, yüklenecek dilimi önce silip sonra eklemektir:

CREATE TABLE aylik_ciro (ay VARCHAR(7), ciro DECIMAL(12, 2));

-- Aynı adımı iki kez çalıştırıyoruz:
DELETE FROM aylik_ciro WHERE ay = '2024-12';
INSERT INTO aylik_ciro (ay, ciro)
SELECT '2024-12', ROUND(SUM(oi.quantity * oi.unit_price * (1 - oi.discount)), 2)
FROM orders o JOIN order_items oi ON oi.order_id = o.order_id
WHERE o.status = 'delivered' AND o.order_date >= '2024-12-01' AND o.order_date < '2025-01-01';

DELETE FROM aylik_ciro WHERE ay = '2024-12';
INSERT INTO aylik_ciro (ay, ciro)
SELECT '2024-12', ROUND(SUM(oi.quantity * oi.unit_price * (1 - oi.discount)), 2)
FROM orders o JOIN order_items oi ON oi.order_id = o.order_id
WHERE o.status = 'delivered' AND o.order_date >= '2024-12-01' AND o.order_date < '2025-01-01';

SELECT ay, ciro, (SELECT COUNT(*) FROM aylik_ciro) AS satir FROM aylik_ciro;

İki çalıştırmadan sonra da tabloda tek satır var. Gerçek sistemlerde DELETE ile INSERT aynı işlem (transaction) içinde yapılır; böylece arada okuyan bir rapor boş tablo görmez. Diğer idempotent kalıplar: MERGE (upsert), CREATE OR REPLACE TABLE ve bölüm üzerine yazma (BigQuery'de WRITE_TRUNCATE).

Pipeline kontrol listesiHam veri değiştirilmeden saklanıyor mu? Her adım idempotent mi? Yüklenen satırlara loaded_at / batch_id ekleniyor mu? Kaynak ve hedef satır sayıları karşılaştırılıyor mu? Hata olursa kim, nasıl haberdar oluyor?
Alıştırmalara geç (7)