Her gece tüm tabloyu yüklemek ölçeklenmez
Milyarlarca satırlık bir olay tablosunu her gün baştan yüklemek pahalıdır. Artımlı yükleme, hedefte en son yüklenen zamanı (watermark) bulur ve sadece ondan yeni kayıtları ekler.
-- Hedef tablo: daha önce 15 Kasım'a kadar yüklenmiş CREATE TABLE price_hist AS SELECT * FROM price_updates WHERE updated_at < '2024-11-15'; -- Artımlı adım INSERT INTO price_hist SELECT * FROM price_updates WHERE updated_at > (SELECT COALESCE(MAX(updated_at), '1900-01-01') FROM price_hist); SELECT COUNT(*), MAX(updated_at) FROM price_hist;
Geç gelen veri
Bazı kayıtlar kaynağa gecikmeli düşer. Yaygın çözüm, watermark'tan biraz geriye giden bir pencereyi (ör. son 3 gün) her seferinde silip yeniden yüklemektir. Bu hem geç gelenleri yakalar hem de idempotenttir:
DELETE FROM fct_events WHERE event_date >= :baslangic; INSERT INTO fct_events SELECT ... FROM raw_events WHERE event_date >= :baslangic;
materialized='incremental' ve {% if is_incremental() %} WHERE updated_at > (SELECT MAX(updated_at) FROM {{ this }}) {% endif %} kalıbı aynı mantığı uygular.Derinleş: watermark, geç gelen veri ve kontrol tablosu
Watermark (su seviyesi), hedefe en son hangi noktaya kadar veri yüklendiğini gösteren değerdir: çoğunlukla bir zaman damgası, bazen artan bir kimlik. Artımlı iş her çalıştığında “watermark'tan sonrasını” okur ve sonunda watermark'ı ilerletir. Watermark'ı hedef tablodan MAX() ile türetmek basittir; ama üretimde genellikle ayrı bir kontrol tablosunda tutulur, çünkü hedef tablo silinip yeniden kurulabilir, birden çok kaynaktan beslenebilir veya boş olabilir.
CREATE TABLE etl_watermark (tablo VARCHAR(30), son_deger VARCHAR(19));
INSERT INTO etl_watermark (tablo, son_deger) VALUES ('price_updates', '2024-11-15 00:00:00');
-- Daha önceki çalıştırmalarla dolmuş hedef
CREATE TABLE price_hist (product_id INTEGER, new_price REAL, updated_at VARCHAR(19));
INSERT INTO price_hist
SELECT product_id, new_price, updated_at FROM price_updates
WHERE updated_at <= '2024-11-15 00:00:00';
-- Artımlı adım: watermark'tan sonrasını ekle, sonra watermark'ı ilerlet
INSERT INTO price_hist
SELECT product_id, new_price, updated_at FROM price_updates
WHERE updated_at > (SELECT son_deger FROM etl_watermark WHERE tablo = 'price_updates');
UPDATE etl_watermark
SET son_deger = (SELECT MAX(updated_at) FROM price_hist)
WHERE tablo = 'price_updates';
SELECT (SELECT COUNT(*) FROM price_hist) AS satir, son_deger FROM etl_watermark;
Watermark yalnızca yükleme başarıyla bittiğinde güncellenmelidir; aynı işlem (transaction) içinde ya da yüklemeden hemen sonra. Önce watermark'ı ilerletip sonra yüklemede hata alırsan aradaki kayıtlar sonsuza dek kaybolur.
> mı >= mı?
> aynı zaman damgasına sahip ama farklı çalıştırmalarda gelen kayıtları kaçırabilir; >= ise son anı iki kez yükler. Güvenli kombinasyon: >= ile oku, hedefe MERGE / NOT EXISTS ile yaz (tekrarı engelle).
Geç gelen veri
Lezzet Kurye'de 94 teslim siparişi, verildiği günden sonraki gün teslim edilmiş (gece yarısını aşan siparişler). Teslim tarihine göre günlük özet üreten bir iş öğlen çalışırsa o günün teslimlerinin bir kısmını henüz görmez. Çözüm, her çalıştırmada son birkaç günü silip yeniden yüklemektir (lookback penceresi). Pencere ne kadar geniş olmalı? Verinin gecikme dağılımına bak: gecikmelerin %99'u 2 gün içindeyse 3 günlük pencere yeterlidir.
| Sorun | Belirti | Çözüm |
|---|---|---|
| Geç gelen kayıt | Geçmiş günlerin sayıları sonradan artar | Lookback penceresiyle sil-yeniden yükle |
| Güncellenen kayıt | Durum değişikliği hedefe yansımaz | updated_at watermark'ı + MERGE |
| Silinen kayıt | Hedefte “hayalet” satırlar | Kaynakta soft delete bayrağı ya da periyodik tam karşılaştırma |
| Saat dilimi | Gün sınırında kayıp/çift | Watermark'ı UTC tut |