İçeriğe geç
academia.sh

Ders 09 / 16

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.

İçindekiler

Ö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.

# 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.

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 birdir.

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.

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_degistinin 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_degistinin 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.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat