---
title: 'Aşamalı Katmanlar'
source: 'https://academia.sh/tr/kurslar/veri-hatlari/asamali-katmanlar'
course: 'Veri Hatları ve Orkestrasyon'
language: tr
updated: '2026-08-17T18:08:50+00:00'
license: 'CC BY-SA 4.0'
---

# Aşamalı Katmanlar

Ham, arıtılmış ve sunum katmanlarının her birinin sakladığı satırın ve bir bozulmanın hangi katmanda durdurulabildiğinin sayılması: sağlam hat ham katmanda 2400, arıtılmış katmanda 2200 satır ve sunum katmanında 55 özet hücresi bırakıyor; altı bozulma sınıfının dördü ham katmanda, biri arıtılmış katmanda, biri de ancak sunum katmanında duruyor ve bunlardan üçü sunulan değeri hiç değiştirmiyor; üç katmanlı kurulum 4655 satır saklayıp altı sınıfın altısını da durdururken iki katmanlı kurulum 2455 satırla aynı altısını durduruyor ama birim değişimini bir katman geç yakalıyor, tek katmanlı kurulum ise 55 hücre saklayıp yalnız iki sınıfı durduruyor ve dördünü hiç görmüyor.

Önceki ders on bir modeli tek bir düzlemde tuttu: hepsi eşit ölçüde kalıcı, hepsi eşit ölçüde
sorgulanabilir. O düzlemde bir modelin çıktısına bakan biri, o sayının kaynaktan mı yoksa dört
dönüşüm sonrasından mı geldiğini ayırt edemez. Kalıcı bir dönüştürme katmanında modeller bu yüzden
tek bir düzlemde durmaz; birbirinin üstüne binen **aşamalı katmanlara (staging layer)** ayrılır ve
her katman farklı bir söz verir.

Bu ders üç katmanı kurar ve iki şeyi ölçer: her katmanın **sakladığı satır** ve bir bozulmanın
**hangi katmanda durdurulabildiği**. İkinci soru birincisine bağlıdır, çünkü bir kural yalnızca
okuyabildiği tabloya bakabilir. Önceki kursta tanımlanan altı bozulma sınıfı bu üç katmana dağıtılır.

- **DN17.** Katmanlar, kurallar ve bozulma sınıfları **kurgudur**; gerçek bir depo, tablo biçimi ya
  da veri testi kitaplığı çağrılmaz. Tohum **20260218**, ölçü koşumdan bağımsızdır.
- **DN18.** Üç katman: **ham** kaynağı olduğu gibi saklar, **arıtılmış** ayıklama, tekilleştirme ve
  tüketim hesabını uygular, **sunum** özet ile yayımlanan değeri taşır. Her katman kendi tablosunu
  bırakır ve sonraki katman öncekini okur.
- **DN19.** Bir kural yalnızca **okuduğu katmanın tablosu saklanıyorsa** koşabilir. Katman
  kaldırıldığında o sınırdaki kurallar da kalkar.
- **DN20.** Altı bozulma sınıfı Veri Mühendisliğine Giriş kursunda tanımlandı ve **tekrarlanmaz**;
  burada girdi olarak kullanılır. Hiçbiri saldırı değildir, hepsi üretici tarafı kazasıdır ve her
  biri tek bir dönemi bozar.
- **DN21.** Yakalama gecikmesini aşama olarak ölçen yordam da o kursta ölçüldü ve tekrarlanmaz.
  Buradaki soru kaç aşama sonra değil, **hangi katmanda** durdurulduğudur.
- **DN22.** Taban çizgisi **tek katmanlı hattır**: yalnızca sunum saklanır, ara tablo yok, ham satır
  yok.
- **DN23.** Sayılan birimler saklanan satır, özet hücresi ve **durdurulan bozulma sınıfıdır**.
- **DN24.** Çözünürlük: satır oranının adımı **0,0004**, özet hücresinin **0,0182**. **Sunum
  üzerinde oran basılmaz**, değerin kendisi yazılır.

## Üç Katman, Üç Ayrı Söz

Katmanlar birbirinin kopyası değildir; her biri farklı bir soruyu yanıtlayabilir hâle gelir ve
karşılığında bir şeyi kaybeder. **Ham katman** kaynaktan geleni değiştirmeden saklar: alan adları,
türler ve yinelenen satırlar olduğu gibi durur. Bu katmanda bir alanın adına ya da bir değerin
türüne bakılabilir, ama tüketimden söz edilemez, çünkü tüketim henüz hesaplanmamıştır.

**Arıtılmış katman** ayıklama, tekilleştirme ve tüketim hesabını uygular. Burada artık satır başına
bir tüketim değeri vardır ve o değerin işaretine, büyüklüğüne, dağılımına bakılabilir. Karşılığında
düşen satırlar kaybolmuştur: arıtılmış katmana bakan biri neyin neden düştüğünü göremez.

**Sunum katmanı** yalnızca yayımlanacak olanı taşır. Beş değer ve onları üreten elli beş özet
hücresi. Bu katmanda tek yapılabilecek şey bugünkü sayıyı dünkü sayıyla karşılaştırmaktır.

```python
# KURGUDUR. Sayac okumalari, katmanlar ve kurallar ders icinde tanimlanir;
# gercek bir depo, tablo bicimi ya da veri testi kitapligi 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


BOZULMA = ["gec_gelen", "yinelenen", "sema_degisti", "birim_degisti",
           "eksik_bolum", "kayan_tip"]


def boz(kayit, sinif, donem="2026-07"):
    """Tek bir donemi bozar , kalan donemler saglam kalir."""
    yeni, sayac = [], 0
    for k in kayit:
        if k["donem"] != donem:
            yeni.append(k)
            continue
        if sinif == "gec_gelen":
            if k["abone"] <= "A040":
                sayac += 1
                continue
            yeni.append(k)
        elif sinif == "yinelenen":
            yeni.append(k)
            if k["abone"] <= "A060":
                yeni.append(dict(k))
                sayac += 1
        elif sinif == "sema_degisti":
            y = dict(k)
            y["endeks_degeri"] = y.pop("endeks")
            sayac += 1
            yeni.append(y)
        elif sinif == "birim_degisti":
            y = dict(k)
            y["endeks"] = k["endeks"] * 1000
            y["birim"] = "m3"
            sayac += 1
            yeni.append(y)
        elif sinif == "eksik_bolum":
            if k["bolge"] == "kuzey":
                sayac += 1
                continue
            yeni.append(k)
        elif sinif == "kayan_tip":
            y = dict(k)
            y["endeks"] = str(k["endeks"])
            sayac += 1
            yeni.append(y)
    return yeni, sayac


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


# ---- UC KATMAN: her biri kendi tablosunu birakir
KATMAN = ["ham", "aritilmis", "sunum"]


def katmanla(kayit):
    v = kayit
    for f in (a1_ayikla, a2_tekille, a3_tuketim):
        v, _ = f(v)
    ozet, _ = a4_ozet(v)
    sunum, _ = a5_sun(ozet)
    return {"ham": kayit, "aritilmis": v, "ozet": ozet, "sunum": sunum}
```

Kurallar katmanların **sınırlarına** yerleşir ve her biri yalnızca kendi katmanının tablosunu okur.
Alan, tür ve anahtar kuralları ham katmanı okur. Satır sayısı ve tüketimin işareti arıtılmış katmanı
okur; ikincisi ham katmanda **yazılamaz**, çünkü orada tüketim yoktur. Dağılım kuralı özeti okur.

```python
def d_sema(v, alanlar=("abone", "donem", "bolge", "endeks", "birim")):
    return any(any(a not in k for a in alanlar) for k in v)


def d_tip(v):
    return any(not isinstance(k.get("endeks"), int) for k in v)


def d_tekillik(v):
    ad = [(k["abone"], k["donem"]) for k in v]
    return len(ad) != len(set(ad))


def d_bolum_donem(v):
    gor = set((k["bolge"], k["donem"]) for k in v)
    return gor != set((b, d) for b in BOLGE for d in DONEM)


def d_negatif(v):
    """Endeks artan oldugu icin saglam hatta tuketim hic negatif olmaz."""
    return any(k["m3"] < 0 for k in v)


def d_satir_sayisi(v, beklenen, pay=0.05):
    return abs(len(v) - beklenen) / beklenen > pay


def d_dagilim(ozet, taban, pay=0.25):
    for ad, v in ozet.items():
        t = taban.get(ad)
        if t and abs(v - t) / max(abs(t), 1) > pay:
            return True
    return False


KURAL = [
    ("sema", "ham", lambda kt, t: d_sema(kt["ham"])),
    ("tip", "ham", lambda kt, t: d_tip(kt["ham"])),
    ("tekillik", "ham", lambda kt, t: d_tekillik(kt["ham"])),
    ("bolum_donem", "ham", lambda kt, t: d_bolum_donem(kt["ham"])),
    ("satir_sayisi", "aritilmis", lambda kt, t: d_satir_sayisi(kt["aritilmis"], t["satir"])),
    ("negatif", "aritilmis", lambda kt, t: d_negatif(kt["aritilmis"])),
    ("dagilim", "sunum", lambda kt, t: d_dagilim(kt["ozet"], t["ozet"])),
]


def duran(kt, taban, acik=KATMAN):
    """Bozulmayi ilk durduran katman ve o katmanda atesleyen kural."""
    for kat in KATMAN:
        if kat not in acik:
            continue
        for ad, k, f in KURAL:
            if k == kat and f(kt, taban):
                return kat, ad
    return "-", "-"


KAYNAK_KAYIT = kaynak_uret()
T = katmanla(KAYNAK_KAYIT)
TABAN = {"satir": len(T["aritilmis"]), "ozet": T["ozet"], "sunum": T["sunum"]}
print("saglam hat  ham:", len(T["ham"]), " aritilmis:", len(T["aritilmis"]),
      " ozet hucresi:", len(T["ozet"]), " sunum:", len(T["sunum"]))
print("saglam hatta atesleyen kural:", duran(T, TABAN)[1])
print()

print(f"{'bozulma':<15}{'ham':>6}{'aritilmis':>11}{'ozet':>6}{'sunum':>9}"
      f"{'duran katman':>14}{'kural':>14}")
for s in BOZULMA:
    bozuk, _ = boz(KAYNAK_KAYIT, s)
    kt = katmanla(bozuk)
    kat, kural = duran(kt, TABAN)
    print(f"{s:<15}{len(kt['ham']):>6}{len(kt['aritilmis']):>11}{len(kt['ozet']):>6}"
          f"{('ayni' if kt['sunum'] == TABAN['sunum'] else 'degisti'):>9}{kat:>14}{kural:>14}")
```

```
saglam hat  ham: 2400  aritilmis: 2200  ozet hucresi: 55  sunum: 5
saglam hatta atesleyen kural: -

bozulma           ham  aritilmis  ozet    sunum  duran katman         kural
gec_gelen        2360       2120    55  degisti         sunum       dagilim
yinelenen        2460       2200    55     ayni           ham      tekillik
sema_degisti     2400       1800    45  degisti           ham          sema
birim_degisti    2400       2200    55     ayni     aritilmis       negatif
eksik_bolum      2354       2108    53  degisti           ham   bolum_donem
kayan_tip        2400       2200    55     ayni           ham           tip
```

## Bozulma Hangi Katmanda Duruyor

Sağlam hat üç katmanda sırasıyla **2400 satır**, **2200 satır** ve **55 özet hücresi** bırakıyor;
hiçbir kural ateşlemiyor. Bozulmuş koşumların dağılımı ise **dört, bir ve bir**dir.

Ham katman dört sınıfı durduruyor ve dördü de aynı nedenle: `yinelenen`, `sema_degisti`,
`eksik_bolum` ve `kayan_tip` **satırın kendisinde** görünür. Alan eksik, tür kaymış, anahtar
yinelenmiş ya da bir bölge–dönem çifti hiç yok. Ham katman satırı olduğu gibi sakladığı için bu
dördüne bakabilir. Bir dönüşüm uygulanmış olsaydı bunların çoğu **görünmez olurdu**: `kayan_tip`
satırının kanıtı arıtılmış katmanda yoktur, çünkü tüketim hesabı metne dönmüş sayıyı sessizce
yeniden sayıya çevirir ve satır düşmez.

Arıtılmış katman tek bir sınıfı durduruyor: `birim_degisti`. Bunu yapan kural tüketimin **negatif**
olamayacağını söyler; endeks artan olduğu için sağlam hatta hiç ateşlemez. Kural ham katmanda
yazılamazdı, çünkü ham katmanda tüketim diye bir şey yoktur, yalnızca endeks vardır. Bu, katmanın
varlık nedeninin en açık kanıtıdır: **arıtılmış katman yeni bir alan üretir ve o alanın üstüne yeni
bir kural yazılabilir hâle gelir.**

Sunum katmanı da tek bir sınıfı durduruyor: `gec_gelen`. Kırk satır hiç gelmemiş, arıtılmış katman
2120'ye inmiş ama bu düşüş satır sayısı kuralının yüzde beşlik payını aşmamış. Bozulma iki katmanı
da geçip özete girdikten sonra, ancak dağılım karşılaştırmasıyla görünüyor. **O noktada bozulma
zaten iki tabloyu kirletmiştir** ve onarım yalnızca sunumu değil, altındaki iki katmanı da
kapsamak zorundadır.

Son sütunlar dersin sessiz bulgusunu taşır. Yakalanan altı sınıftan **üçü** sunulan beş değeri
**hiç değiştirmiyor**: `yinelenen`, `birim_degisti` ve `kayan_tip`. Üçü de yakalandı, ama hiçbiri
çıktıya bakılarak fark edilemezdi. `birim_degisti` en açık örnektir: ham katmanda 2400, arıtılmış
katmanda 2200 satır, özette 55 hücre ve sunumda tabanla birebir aynı beş değer. Yalnızca ara
katmandaki tüketimin işareti bozulmanın olduğunu söylüyor.

## Katman Kaldırıldığında

Üç katman bedava değildir. Aynı veri üç ayrı biçimde saklanır ve her katman ayrı bir yazma işi,
ayrı bir tazelik sorusu, ayrı bir sahiplik getirir. Son blok katmanları teker teker kaldırır ve
durdurulan bozulma sınıfı sayısını saklanan satırın yanına koyar.

```python
KURULUM = [("uc katman", KATMAN), ("iki katman", ["ham", "sunum"]),
           ("tek katman", ["sunum"])]
print(f"{'kurulum':<12}{'saklanan satir':>16}{'durdurulan':>12}"
      f"{'sunum katmaninda':>18}  yakalanmayan")
for ad, acik in KURULUM:
    saklanan = sum(len(T[k]) if k != "sunum" else len(T["ozet"]) for k in acik)
    durdurulan, gec, kacan = 0, 0, []
    for s in BOZULMA:
        bozuk, _ = boz(KAYNAK_KAYIT, s)
        kat, _ = duran(katmanla(bozuk), TABAN, acik)
        if kat == "-":
            kacan.append(s)
        else:
            durdurulan += 1
            gec += kat == "sunum"
    print(f"{ad:<12}{saklanan:>16}{durdurulan:>12}{gec:>18}  {kacan}")
```

```
kurulum       saklanan satir  durdurulan  sunum katmaninda  yakalanmayan
uc katman               4655           6                 1  []
iki katman              2455           6                 2  []
tek katman                55           2                 2  ['yinelenen', 'sema_degisti', 'eksik_bolum', 'kayan_tip']
```

İkinci satır arıtılmış katmanın gerçek katkısını verir. Ham ve sunum katmanları saklanırken altı
sınıfın altısı da durduruluyor; tek fark `birim_degisti`nin artık dağılım kuralına kalmasıdır, yani
**bir katman geç** yakalanmasıdır. Arıtılmış katmanın satın aldığı şey budur ve bedeli **2200
satırdır**. Bir katmanın değeri her zaman yeni bir bozulma sınıfı yakalamak değildir; çoğu zaman
aynı sınıfı **daha yukarıda** yakalamaktır.

Üçüncü satır taban çizgisidir ve dersin en sert sayısını taşır. Yalnızca sunum saklandığında toplam
depolama 55 hücreye iniyor, ama durdurulan bozulma sınıfı **altıdan ikiye** düşüyor. Yakalanmayan
dört sınıf listede adıyla yazılıdır. Bunların ikisi (`sema_degisti`, `eksik_bolum`) sunulan değeri
değiştiriyor, yani dikkatli bir okuyucunun bir gün fark etme ihtimali var. Öbür ikisi
(`yinelenen`, `kayan_tip`) sunulan değeri **hiç değiştirmiyor**: tek katmanlı bir hatta bu iki
bozulma sınıfı için bakılabilecek hiçbir yer yoktur, çünkü kanıtı taşıyan tablo saklanmamıştır.

Bu, kursun kuralının katman düzeyindeki karşılığıdır. Tek katmanlı hat çalışır, sayı üretir ve
altı bozulmanın dördünde hiçbir şey söylemez. **Bozulmayı gösterebilecek tabloyu saklamayan bir
hat, o bozulma için ölçülmemiş sayılır.** Katmanların 4655'e karşı 55 satırlık bedeli, tam olarak
bu ölçülebilirliğin fiyatıdır.

## Özet

- Üç katman üç ayrı söz verir: ham katman satırı olduğu gibi saklar, arıtılmış katman tüketim
  değerini üretir, sunum katmanı yalnızca yayımlanacak olanı taşır. Sağlam hatta sırasıyla
  **2400 satır, 2200 satır ve 55 özet hücresi** bırakırlar.
- Bir kural yalnızca okuduğu katmanın tablosu saklanıyorsa koşabilir; tüketimin işaretine bakan
  kural ham katmanda **yazılamaz**, çünkü orada tüketim yoktur.
- Altı bozulma sınıfının **dördü** ham katmanda, **biri** arıtılmış katmanda, **biri** ancak sunum
  katmanında duruyor; sonuncusu durdurulduğunda alttaki iki tablo çoktan kirlenmiştir.
- Yakalanan altı sınıftan **üçü** sunulan beş değeri hiç değiştirmiyor; `birim_degisti`nin tek
  kanıtı arıtılmış katmandaki negatif tüketimdir.
- Arıtılmış katman kaldırıldığında durdurulan sınıf sayısı düşmez, ama `birim_degisti` **bir katman
  geç** yakalanır; katmanın 2200 satırlık bedeli bu bir katmanı satın alır.
- Yalnızca sunum saklandığında depolama 55 hücreye iner ve durdurulan sınıf **altıdan ikiye** düşer;
  yakalanmayan dördün ikisi sunulan değeri de değiştirmediği için bakılabilecek hiçbir yer kalmaz.

## Sonraki Adım

Bu dersin kuralları hattın **taşıdığı satıra** bakıyordu: alan var mı, tür doğru mu, anahtar tekil
mi, tüketim negatif mi. Hepsi verinin kendisi hakkındaydı ve hiçbiri dönüşümün kendisi hakkında bir
şey söylemedi. Bir dönüşüm doğru veriyi alıp yanlış hesaplayabilir; toplama yanlış anahtarla
gruplanabilir, katsayı yanlış tipe uygulanabilir, birleştirme satır çoğaltabilir. Bu durumların
hiçbiri girdide görünmez ve hiçbiri katman sınırındaki kurallara takılmaz. Sonraki ders kuralı
verinin üstünden **dönüşümün çıktısının üstüne** taşır: her dönüşümün kendi çıktısına konan beklenti
yazılır, kaç bozulma sınıfını yakaladığı sayılır ve hiçbir beklentinin yakalamadığı kalıntı ölçülür.
