---
title: 'ETL ve ELT'
source: 'https://academia.sh/tr/kurslar/veri-hatlari/etl-ve-elt'
course: 'Veri Hatları ve Orkestrasyon'
language: tr
updated: '2026-08-17T18:08:50+00:00'
license: 'CC BY-SA 4.0'
---

# ETL ve ELT

Dönüştürmenin kaynakta mı hedefte mi koşacağının sayılması: sınır kaynağa alındığında hedefe taşınan satır 2400'den 55'e, taşınan hücre 14400'den 165'e iniyor, ama üç kurulumun da okuduğu toplam hücre 33110'da sabit kalıyor ve yalnızca okuyanın kim olduğu değişiyor; karma sınır taşınan satırı 2200'e düşürürken taşınan hücreyi 15400'e çıkarıyor; bir raporlama kuralı değiştiğinde hedefte yeniden hesaplanabilen kural sayısı ham veriyi saklayan kurulumda 3, karma kurulumda 1, kaynakta dönüştüren kurulumda 0 oluyor ve son kurulum kaynağa dönmek zorunda kalıp yalnızca üç dönemi geri hesaplayabiliyor.

Bu kursun ilk altı dersi veriyi hatta **aldı**: kaynaktan çekildi, sıraya girdi, teslim edildi ve
işlenmiş hâliyle geri döndü. Hepsinin ortak varsayımı tek cümleyle yazılabilir: veri bir yerden
alınır ve bir yere konur. Hiçbirinde verinin **ne hâle getirildiği** sorulmadı.

Bu ders o soruyu ilk kararla açar: dönüştürme **nerede** koşacak. Kaynağın yanında mı, yoksa veri
hedefe taşındıktan sonra orada mı. İki yanıt iki kalıbın adıdır ve aralarındaki fark bir takastır:
kaynakta dönüştürmek **taşınan satırı** düşürür, hedefte dönüştürmek **ham veriyi korur** ve
yeniden hesaplamayı mümkün kılar. Bu derste ikisi yan yana koşar.

- **DN1.** Kaynak, hat ve bölünme **kurgudur**; gerçek bir depo, sorgu motoru ya da dönüştürme
  çerçevesi çağrılmaz. Tohum **20260218**, ölçü koşumdan bağımsızdır.
- **DN2.** **ETL** çıkar–dönüştür–yükle, **ELT** çıkar–yükle–dönüştür demektir. İkisi de birer
  kalıp adıdır, ürün adı değildir; aralarındaki tek fark dönüşümün hangi tarafta koştuğudur.
- **DN3.** Hattın beş aşaması tek bir **sınırla** ikiye ayrılır. Sınırdan önceki aşamalar kaynak
  tarafında, kalanlar hedefte koşar. ETL sınırı **4**, ELT sınırı **0**'dır.
- **DN4.** Okunan hücre bir modeldir: her aşama, girdisindeki her satırın bildirilen sayıda alanını
  okur. Sayı bir donanım ölçümü değil, aşamanın **iş yükünün** ölçüsüdür.
- **DN5.** Taban çizgisi **bölünmemiş hattır**: sınır kararı yok, yeniden hesaplama sorulmamış.
- **DN6.** Kaynak operasyonel bir sistemdir ve yalnızca **son üç dönemi** saklar; hedef on iki
  dönemin tamamını saklar.
- **DN7.** Depolama düzeni, bölümleme ve maliyet Veri Depolama Mimarileri kursunda ölçüldü ve
  **tekrarlanmaz**. Buradaki soru satırın nerede durduğu değil, dönüşümün nerede koştuğudur.
- **DN8.** Çözünürlük: satır oranının adımı **0,0004**. **Sunum üzerinde oran basılmaz**, değerin
  kendisi yazılır.

## Sınır Nerede Duruyor

Hattın beş aşaması sabittir: ayıklama, tekilleştirme, tüketim hesabı, özet ve sunum. Değişen tek
şey bu zincirin **nerede kesildiğidir**. Sınır sıfırdaysa hiçbir aşama kaynakta koşmaz, ham satırlar
olduğu gibi hedefe taşınır ve beş aşamanın tamamı orada işler. Sınır dörtteyse dört aşama kaynağın
yanında koşar, hedefe yalnızca özet tablosu gider.

Sınırın seçilmesi bir mimari tercih değil, iki büyüklük arasında yapılan bir takastır. Aşağıdaki kod
o iki büyüklüğü sayar: sınırdan geçen satır ve her iki tarafın okuduğu hücre.

```python
# KURGUDUR. Sayac okumalari, bes asamali hat ve bolunme ders icinde tanimlanir;
# gercek bir depo, sorgu motoru ya da donusturme cercevesi cagrilmaz.
TOHUM, M32 = 20260218, 0xFFFFFFFF


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
DONEM = [f"2026-{a:02d}" for a in range(1, 13)]
ABONE = {}
for i in range(200):
    r = uretec(TOHUM + 37 * i)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "baslangic": 10000 + int(r() * 60000)}


def kaynak_uret():
    kayit = []
    for i, (ab, a) in enumerate(ABONE.items()):
        e = a["baslangic"]
        for d in DONEM:
            r = uretec(TOHUM + 101 * i + 7 * DONEM.index(d))
            e += 4 + int(r() * 46)
            kayit.append({"abone": ab, "donem": d, "bolge": a["bolge"], "tip": a["tip"],
                          "endeks": e, "birim": "m3"})
    return kayit


# ---- HAT: bes asama, her biri kendi dusurdugu satiri sayar
def a1_ayikla(kayit):
    ZOR = ("abone", "donem", "bolge", "endeks", "birim")
    tut = [k for k in kayit if all(a in k for a in ZOR)]
    return tut, len(kayit) - len(tut)


def a2_tekille(kayit):
    gor, tut = set(), []
    for k in kayit:
        ad = (k["abone"], k["donem"])
        if ad in gor:
            continue
        gor.add(ad)
        tut.append(k)
    return tut, len(kayit) - len(tut)


def a3_tuketim(kayit):
    tablo = {(k["abone"], k["donem"]): k for k in kayit}
    cikti, dusen = [], 0
    for k in kayit:
        i = DONEM.index(k["donem"])
        if i == 0:
            continue
        onceki = tablo.get((k["abone"], DONEM[i - 1]))
        if onceki is None:
            dusen += 1
            continue
        try:
            f = int(k["endeks"]) - int(onceki["endeks"])
        except (TypeError, ValueError):
            dusen += 1
            continue
        cikti.append(dict(k, m3=f))
    return cikti, dusen


def a4_ozet(kayit):
    top = {}
    for k in kayit:
        ad = (k["bolge"], k["donem"])
        top[ad] = top.get(ad, 0) + k["m3"]
    return top, 0


def a5_sun(ozet):
    bolge = {}
    for (b, d), v in ozet.items():
        bolge.setdefault(b, []).append(v)
    return {b: round(sum(v) / len(v), 2) for b, v in bolge.items()}, 0


ASAMA = [("ayikla", a1_ayikla), ("tekille", a2_tekille), ("tuketim", a3_tuketim),
         ("ozet", a4_ozet), ("sun", a5_sun)]

# ---- Okunan hucre: her asama girdisindeki her satirin su kadar alanini okur.
OKUNAN_ALAN = {"ayikla": 5, "tekille": 2, "tuketim": 4, "ozet": 3, "sun": 2}


def hucre(veri):
    """Ozet sozlugu hucre basina uc deger tasir , kayit ise kendi alanlarini."""
    if isinstance(veri, dict):
        return len(veri) * 3
    return sum(len(k) for k in veri)


def bolunmus_hat(kayit, sinir):
    """Ilk `sinir` asama kaynak tarafinda , kalani hedefte kosar.
    Sinirdan gecen sey `sinir` asamasinin ciktisidir."""
    okunan, veri, tasinan = {"kaynak": 0, "hedef": 0}, kayit, kayit
    for i, (ad, f) in enumerate(ASAMA):
        okunan["kaynak" if i < sinir else "hedef"] += len(veri) * OKUNAN_ALAN[ad]
        veri, _ = f(veri)
        if i + 1 == sinir:
            tasinan = veri
    return veri, okunan, tasinan
```

## Taşınan Satır ve Okunan Hücre

İkinci blok aynı kaynağı üç sınırla koşturur. `tasinan` sınırdan geçen satırı, `tas.hucre` o
satırların taşıdığı alan sayısını, `kaynak` ile `hedef` iki tarafın okuduğu hücreyi verir. Son sütun
sunulan beş değerin tabanla aynı kalıp kalmadığını yazar.

```python
KAYNAK_KAYIT = kaynak_uret()
KURULUM = [("hedefte (ELT)", 0), ("karma", 3), ("kaynakta (ETL)", 4)]
TABAN, _, _ = bolunmus_hat(KAYNAK_KAYIT, 0)

print("taban sunum:", TABAN)
print(f"{'kurulum':<16}{'sinir':>6}{'tasinan':>9}{'tas.hucre':>11}"
      f"{'kaynak':>8}{'hedef':>7}{'sunum':>8}")
for ad, n in KURULUM:
    sunum, ok, tas = bolunmus_hat(KAYNAK_KAYIT, n)
    print(f"{ad:<16}{n:>6}{len(tas):>9}{hucre(tas):>11}{ok['kaynak']:>8}{ok['hedef']:>7}"
          f"{'ayni' if sunum == TABAN else 'degisti':>8}")
```

```
taban sunum: {'merkez': 1321.45, 'kuzey': 1212.55, 'dogu': 881.36, 'bati': 833.09, 'guney': 1065.55}
kurulum          sinir  tasinan  tas.hucre  kaynak  hedef   sunum
hedefte (ELT)        0     2400      14400       0  33110    ayni
karma                3     2200      15400   26400   6710    ayni
kaynakta (ETL)       4       55        165   33000    110    ayni
```

Son sütun üç kurulumda da **aynı**dır: sınır nereye konursa konsun sunulan beş değer birebir aynı
çıkıyor. Kararın çıktı üzerinde hiçbir etkisi yok; bütün etkisi çıktının **nasıl** üretildiğinde.

İlk iki sütun beklenen takası verir. Kaynakta dönüştüren kurulum hedefe **55 satır** ve **165 hücre**
taşıyor; hedefte dönüştüren kurulum **2400 satır** ve **14400 hücre**. Taşınan satırdaki oran
43,6'dır ve bu, ağ üzerinden taşınan verinin ölçülebilir tek büyüklüğüdür.

Karma satır bu takasın düz bir doğru olmadığını gösterir. Sınır üçe alındığında taşınan satır
2400'den **2200**'e iniyor, ama taşınan hücre 14400'den **15400**'e **çıkıyor**. Nedeni tüketim
aşamasının her satıra `m3` alanını eklemesidir: satır sayısı azalırken satır başına alan artıyor.
**Taşınan satırı düşürmek taşınan veriyi düşürmek anlamına gelmez.**

Son iki sütun dersin en önemli sayısıdır. Üç kurulumun okuduğu hücre toplamı sırasıyla 33110, 26400
ile 6710 toplamı olan 33110, ve 33000 ile 110 toplamı olan 33110'dur. **Üçü de aynıdır.** Sınır
kararı hesaplama işini yok etmiyor, yalnızca **kimin yaptığını** değiştiriyor. Kaynakta dönüştürmek
33000 hücrelik okumayı operasyonel sistemin üstüne yıkar; hedefte dönüştürmek aynı yükü hedefe
taşır. Bir kurulumu "ucuz" diye seçmek, yükün nereye bindiğini görmemektir.

İki tarafın bu yükü karşılama biçimi de aynı değildir. Kaynak operasyonel bir sistemdir ve asıl işi
dönüşüm koşturmak değil, kendi uygulamasına hizmet etmektir; 33000 hücrelik okuma orada, o hizmetle
aynı kaynağı paylaşarak koşar. Hedef ise yalnızca bu iş için ayrılmıştır. Dolayısıyla eşit görünen
iki sayı eşit değildir: kaynakta okunan hücre başka bir işten çalınır, hedefte okunan hücre çalınmaz.
Dönüşüm zinciri her büyüdüğünde bu fark büyür, çünkü eklenen her aşama sınırın hangi tarafındaysa o
tarafın yükünü artırır. Dönüşümün SQL ile yazılıyor olması bu kararı değiştirmez: dil bir seçim,
sınır ayrı bir seçimdir ve aynı sorgu iki tarafta da yazılabilir.

## Yeniden Hesaplamanın Bedeli

Buraya kadar iki kurulum arasında ölçülebilir bir üstünlük yok. Fark, hat **ikinci kez** koştuğunda
ortaya çıkar. Bir raporlama kuralı değişir: işyeri tüketimi bundan sonra 1,05 katsayıyla
raporlanacak. Kural değişikliğinin hedefte uygulanabilmesi, hedefte **hangi aşamanın çıktısının**
durduğuna bağlıdır.

```python
KURAL = {"isyeri katsayisi 1,05": 3, "tekillestirme anahtari": 1, "birim duzeltmesi": 0}
KAYNAK_SAKLAMA = 3        # operasyonel kaynak yalnizca son uc donemi tutuyor

print(f"{'kural':<24}{'gereken sinir':>14}" + "".join(f"{a:>16}" for a, _ in KURULUM))
for kural, g in KURAL.items():
    print(f"{kural:<24}{g:>14}" + "".join(f"{('evet' if n <= g else 'hayir'):>16}"
                                          for _, n in KURULUM))
print(f"{'hedefte hesaplanabilen':<24}{'':>14}"
      + "".join(f"{sum(1 for g in KURAL.values() if n <= g):>16}" for _, n in KURULUM))
print()


def isyeri_kurali(sinir):
    """Hedef yalnizca kendi elindeki veriyle yeniden hesaplamaya calisir."""
    _, _, tas = bolunmus_hat(KAYNAK_KAYIT, sinir)
    if sinir > KURAL["isyeri katsayisi 1,05"]:
        return None, "evet", len(KAYNAK_KAYIT), KAYNAK_SAKLAMA
    v = tas
    if not any("m3" in k for k in v):
        v, _ = a1_ayikla(v)
        v, _ = a2_tekille(v)
        v, _ = a3_tuketim(v)
    yeni = [dict(k, m3=k["m3"] * (1.05 if k["tip"] == "isyeri" else 1.0)) for k in v]
    oz, _ = a4_ozet(yeni)
    sun, _ = a5_sun(oz)
    return sun, "hayir", 0, len(DONEM)


print(f"{'kurulum':<16}{'kaynaga donus':>15}{'yeniden okunan':>16}{'donem':>7}  sunum")
for ad, n in KURULUM:
    sun, donus, okunan, donem = isyeri_kurali(n)
    print(f"{ad:<16}{donus:>15}{okunan:>16}{donem:>7}  {sun if sun else 'hedefte yok'}")
print()
TASINABILIR = len(KAYNAK_KAYIT) // len(DONEM) * KAYNAK_SAKLAMA
print("siniri 4'ten 0'a kaydirmak: tasinacak gecmis", len(KAYNAK_KAYIT),
      " kaynaktan gelebilen", TASINABILIR,
      " kalici olarak yok", len(KAYNAK_KAYIT) - TASINABILIR)
```

```
kural                    gereken sinir   hedefte (ELT)           karma  kaynakta (ETL)
isyeri katsayisi 1,05                3            evet            evet           hayir
tekillestirme anahtari               1            evet           hayir           hayir
birim duzeltmesi                     0            evet           hayir           hayir
hedefte hesaplanabilen                               3               1               0

kurulum           kaynaga donus  yeniden okunan  donem  sunum
hedefte (ELT)             hayir               0     12  {'merkez': 1357.32, 'kuzey': 1235.57, 'dogu': 902.13, 'bati': 859.22, 'guney': 1095.81}
karma                     hayir               0     12  {'merkez': 1357.32, 'kuzey': 1235.57, 'dogu': 902.13, 'bati': 859.22, 'guney': 1095.81}
kaynakta (ETL)             evet            2400      3  hedefte yok

siniri 4'ten 0'a kaydirmak: tasinacak gecmis 2400  kaynaktan gelebilen 600  kalici olarak yok 1800
```

Üç kural üç ayrı sınır ister. İşyeri katsayısı tüketim satırına, tekilleştirme anahtarının
değiştirilmesi tekilleştirmeden önceki satıra, birim düzeltmesi ise ham endeksin kendisine
dokunur. Bir hedef, ancak kendi elindeki çıktı o sınırdan **önce** duruyorsa kuralı uygulayabilir.
Sayı budur: hedefte hesaplanabilen kural ELT kurulumunda **3**, karma kurulumda **1**, ETL
kurulumunda **0**.

İkinci tablo bunun ne demek olduğunu yazar. İlk iki kurulum kaynağa hiç dönmeden, **0 satır**
yeniden taşıyarak on iki dönemin tamamını yeniden hesaplıyor ve yeni sunumu üretiyor. Üçüncü kurulum
hedefte yalnızca 55 özet hücresi tuttuğu için işyeri ile mesken ayrımını göremiyor; kuralı
uygulamanın tek yolu kaynağa dönüp **2400 satırı** yeniden okumak. Kaynak operasyonel bir sistemdir
ve son üç dönemi saklar: yeniden hesaplanabilen dönem **3**, geri kalan **dokuz dönem** hiçbir
biçimde geri getirilemez.

Bu, kursun kuralının ilk somut karşılığıdır: bir hattın sayısı yeniden koşturulduğunda aynı sonucu
vermesidir ve **yeniden koşturulamayan hat ölçülmemiş sayılır**. Kaynakta dönüştüren kurulum ilk
koşumda kusursuz çalışıyor, taşınan satırı 43,6 kat düşürüyor ve doğru sunumu üretiyor. Dokuz dönemi
yeniden hesaplayamadığı an ise o sayıların hiçbiri savunulabilir olmaktan çıkıyor.

Bedelin öbür yüzü de yazılmalıdır. Ham veriyi hedefte saklamak 2400 satırı iki yerde birden tutmak
demektir ve hedefin okuduğu hücre 110'dan 33110'a çıkar. ELT kurulumu yeniden hesaplama hakkını
bedava almıyor; **hedefte üç yüz kat daha fazla hücre okuyarak** satın alıyor.

## Sınırı Sonradan Kaydırmak

Sınırın bir kez seçilip bırakıldığı varsayımı da yanlıştır. Hedefin kapasitesi büyüdükçe ya da
yeniden hesaplama ihtiyacı ortaya çıktıkça sınır kaynağa doğru değil, hedefe doğru kaydırılmak
istenir. Blok sonundaki son satır bu taşınmanın bedelini yazar.

Sınırı dörtten sıfıra almak, hedefte bugüne kadar hiç durmamış olan ham satırların oraya
getirilmesini gerektirir: **2400 satır**. Bunların kaynaktan gelebilecek olanı yalnızca saklanan üç
dönemin satırlarıdır, yani **600**. Kalan **1800 satır** hiçbir yerde durmuyor ve hiçbir biçimde geri
getirilemez. Sınır kaydırıldıktan sonra hat yeni kurallarla ileriye doğru koşabilir, ama dokuz
dönemlik geçmişi yeniden hesaplaması artık kalıcı olarak imkânsızdır.

Buradan çıkan sonuç sınırın nereye konacağından daha keskindir: **sınır kararı, geçmişe dönük olarak
düzeltilemeyen tek karardır.** Yanlış katsayı düzeltilebilir, düşen satır yeniden alınabilir, kusurlu
bir denetim değiştirilebilir. Saklanmamış ham satır ise geri gelmez ve onunla birlikte, o dönemlere
ait bütün sayıların yeniden koşturulabilirliği de gider.

## Özet

- Bir dönüştürme kararı, beş aşamalı zincirin **nerede kesildiğinden** ibarettir. ETL sınırı 4,
  ELT sınırı 0'dır ve üç kurulum da birebir aynı sunumu üretir.
- Kaynakta dönüştürmek hedefe **55 satır ve 165 hücre** taşır, hedefte dönüştürmek **2400 satır ve
  14400 hücre**; taşınan satırdaki oran 43,6'dır.
- Taşınan satırı düşürmek taşınan veriyi düşürmez: karma sınır satırı 2200'e indirirken taşınan
  hücreyi 15400'e çıkarır, çünkü tüketim aşaması her satıra bir alan ekler.
- Üç kurulumun okuduğu toplam hücre **33110'da sabittir**. Sınır kararı işi yok etmez, yalnızca
  kaynak ile hedef arasında yer değiştirir.
- Bir kural değiştiğinde hedefte yeniden hesaplanabilen kural sayısı **3, 1 ve 0**'dır; kaynakta
  dönüştüren kurulum kaynağa dönmek zorunda kalır ve kaynak üç dönem sakladığı için **dokuz dönem**
  geri getirilemez.
- Ham veriyi hedefte saklamanın bedeli hedefte okunan hücrenin 110'dan 33110'a çıkmasıdır; yeniden
  hesaplama hakkı bu bedelle satın alınır.

## Sonraki Adım

Bu dersin üç kurulumu da tek bir varsayımı paylaşıyordu: dönüşüm beş aşamalı, sırası sabit ve elle
yazılabilir bir zincirdir. Gerçek bir dönüştürme katmanı tek bir zincir değil, birbirine referans
veren onlarca ayrı çıktıdır ve hangisinin hangisinden önce koşacağı elle tutulan bir listede
yazılıdır. O liste her yeni çıktı eklendiğinde bozulur. Sonraki ders dönüşümleri birbirine referans
veren **model**ler olarak yazar, bağımlılığı referansın kendisinden çıkarır ve iki sayıyı yan yana
koyar: bağımlılık çözümünün sıraladığı görev ile elle tutulan sıranın **kaçırdığı bağımlılık**.
