İçeriğe geç
academia.sh

Ders 06 / 12

Meta Veri Kataloğu

Bir veri varlığını bulmak için bakılan giriş sayısının katalog varken ve yokken sayılması: on iki varlık ve 119 dosyalık bir kümede beş arama katalogsuz 295, katalogla 29 giriş bakıyor ve en pahalı arama 117'den 11'e iniyor. Katalog bayatladığında sayı geri döner: üç varlık değişince on iki girişin üçü artık var olmayan bir düzeni gösteriyor, aynı beş arama katalogsuz 406, bayat katalogla 251 oluyor, fakat iki arama katalogsuz olandan pahalıya bitiyor (129'a karşı 122 ve 104'e karşı 100), çünkü ölü giriş taranıyor ve ardından tam tarama yine yapılıyor.

İçindekiler

Önceki iki ders bir küme varlık biriktirdi: bir merkezî ambar, birim odaklı alt kümeler ve her biri kendi bölüm anahtarını seçmiş birim ürünleri. Her ölçümde sorunun hangi depoya gideceği zaten biliniyordu; maliyet, adres bilindikten sonra başlıyordu. Gerçekte o adres bir yerde yazılı değilse bulunmaz. Bir birimin ürününün adı, sahibi, taşıdığı sütunlar, bölüm anahtarı ve hangi dönemleri kapsadığı yazılmamışsa, bir soruyu yanıtlayacak varlığı bulmanın kendisi bir arama işidir.

Bu dersin ölçtüğü şey o aramadır. Meta veri kataloğu (metadata catalog) varlık başına tek bir giriş tutar ve arama o girişler üzerinde yapılır; katalog yoksa arama varlıkların dosyaları üzerinde yapılır. İki durumda bakılan giriş sayısı sayılır. Ardından kataloğun kendi kusuru ölçülür: depolama tarafı değiştiğinde kaç giriş artık var olmayan bir düzeni gösteriyor ve bu girişlere güvenen arama ne kadara mal oluyor.

  • DY61. Kaynak, hat, depolama düzeni ve katalog kurgudur ve ders içinde tanımlanır. Hiçbir ambar, göl, katalog ürünü ya da sorgu motoru çağrılmaz. Tohum 20260218.
  • DY62. Bakılan giriş iki türlüdür ve ikisi de tek tek sayılır. Katalogsuz aramada bir varlığın neyi kapsadığını öğrenmek için dosyalarının açılması gerekir; bakılan giriş açılan dosyadır. Katalogla aramada bakılan giriş taranan katalog girişidir.
  • DY63. Varlıklar ada göre sıralı taranır. Arama, göreve yeten ilk varlıkta durur; en ucuz varlığı seçme kararı bu dersin ölçüsünün dışındadır.
  • DY64. Katalog girişi yazıldığı andaki düzeni taşır. Depolama tarafındaki bir değişiklik girişe kendiliğinden yansımaz; yansıması ayrı bir iştir.
  • DY65. Katalogla yapılan arama girişe güvenir ama doğrular: eşleşen girişin varlığı gerçekten göreve yetmiyorsa arama katalogsuz aramaya düşer ve iki bedel toplanır.
  • DY66. Soyağacı ölçüsü Veri Mühendisliğine Giriş kursundaki Veri Soyağacı dersinde ölçüldü; burada tekrarlanmaz. Soyağacının nesnesi bir satırın dayandığı satırlardır; kataloğun nesnesi bir varlığın nerede durduğudur. Biri değeri açıklar, öbürü adresi verir.

Katalog Varken ve Yokken

Küme on iki varlıktan oluşur. Merkezî ambar bütün bölgeleri ve tarife sütununu taşır ama saklama penceresi yüzünden yalnız son altı dönemi tutar. Beş bölge pazarı bütün dönemleri taşır, tarife sütununu taşımaz. Bir tarife pazarı işyeri satırlarını bütün bölgelerden toplar. Beş birim ürünü kendi bölgesinin bütün satırlarını, kendi seçtiği anahtarla saklar. Beş arama görevi bu küme üzerinde koşar.

# KURGUDUR. Olcum aginin sayac okumalari, hat ve depolama duzeni ders icinde
# tanimlanir; hicbir ambar, gol, katalog urunu ya da sorgu motoru 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


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
        cikti.append(dict(k, m3=int(k["endeks"]) - int(onceki["endeks"])))
    return cikti, dusen


def hattan(kaynak):
    v, _ = a1_ayikla(kaynak)
    v, _ = a2_tekille(v)
    v, _ = a3_tuketim(v)
    return v


def yaz(kayitlar, bolumleme=()):
    duzen = {}
    for k in kayitlar:
        duzen.setdefault(tuple(k[a] for a in bolumleme), []).append(k)
    return duzen


TUM = hattan(kaynak_uret())
SON6 = sorted({k["donem"] for k in TUM})[-6:]
TAM = ("abone", "donem", "bolge", "tip", "m3")
BOLGESEL = ("abone", "donem", "bolge", "m3")     # tarife sutunu tasinmiyor
AGIN_ANAHTARI = {"dogu": ("donem",), "bati": ("donem", "tip"), "kuzey": (),
                 "guney": ("donem",), "merkez": ("tip",)}


def varlik(ad, sahip, kayitlar, anahtar, sutun):
    """Bir veri varligi: satirlari , bolumleme anahtari ve tasidigi sutunlar."""
    duzen = yaz(kayitlar, anahtar)
    return {"ad": ad, "sahip": sahip, "anahtar": anahtar, "sutun": sutun,
            "dosya": len(duzen), "satir": {(k["abone"], k["donem"]) for k in kayitlar},
            "bolge": {k["bolge"] for k in kayitlar}, "tip": {k["tip"] for k in kayitlar},
            "donem": {k["donem"] for k in kayitlar}}


def kurulum():
    """Onceki iki dersin biriktirdigi varliklar , ada gore siralanmis."""
    v = [varlik("ambar_merkezi", "merkez ekibi",
                [k for k in TUM if k["donem"] in SON6], ("donem",), TAM)]
    for b in BOLGE:
        v.append(varlik(f"pazar_{b}", f"{b} raporlama",
                        [k for k in TUM if k["bolge"] == b], ("donem",), BOLGESEL))
    v.append(varlik("pazar_tarife", "tarife ekibi",
                    [k for k in TUM if k["tip"] == "isyeri"], ("donem",), TAM))
    for b in BOLGE:
        v.append(varlik(f"urun_{b}", f"{b} birimi",
                        [k for k in TUM if k["bolge"] == b], AGIN_ANAHTARI[b], TAM))
    return sorted(v, key=lambda x: x["ad"])


def gereken(gorev):
    return {(k["abone"], k["donem"]) for k in TUM
            if all(k[a] == d for a, d in gorev.items())}


def gercekte_kapsiyor(v, gorev):
    """Varligin kendisine bakarak: istenen satirlarin hepsi burada mi."""
    return set(gorev) <= set(v["sutun"]) and gereken(gorev) <= v["satir"]


def kayda_gore_kapsiyor(g, gorev):
    """Yalnizca katalog girisine bakarak , dosya acmadan."""
    if not set(gorev) <= set(g["sutun"]):
        return False
    if gorev["donem"] not in g["donem"] or gorev["bolge"] not in g["bolge"]:
        return False
    return {gorev["tip"]} <= g["tip"] if "tip" in gorev else g["tip"] == set(TIP)


def katalog_yaz(varliklar):
    """Varlik basina tek giris: ad , sahip , anahtar , dosya , sutun , kapsam."""
    return [{a: v[a] for a in ("ad", "sahip", "anahtar", "dosya", "sutun",
                               "bolge", "tip", "donem")} for v in varliklar]


def katalogsuz_ara(varliklar, gorev):
    """Sirayla her varligin dosyalari acilir; bakilan giris = acilan dosya."""
    bakilan = 0
    for v in varliklar:
        bakilan += v["dosya"]
        if gercekte_kapsiyor(v, gorev):
            return bakilan, v["ad"]
    return bakilan, None


def kataloglu_ara(varliklar, katalog, gorev):
    """Girisler taranir; eslesen girisin varligi dogrulanir. Bulunamazsa
    katalogsuz aramaya dusulur ve iki maliyet toplanir."""
    ada_gore = {v["ad"]: v for v in varliklar}
    for i, g in enumerate(katalog, 1):
        if not kayda_gore_kapsiyor(g, gorev):
            continue
        v = ada_gore.get(g["ad"])
        if v is not None and gercekte_kapsiyor(v, gorev):
            return i, g["ad"], False
        bakilan, ad = katalogsuz_ara(varliklar, gorev)
        return i + bakilan, ad, True
    return len(katalog), None, False


GOREV = [("kuzey / 2026-03 / isyeri", {"bolge": "kuzey", "donem": "2026-03", "tip": "isyeri"}),
         ("guney / 2026-02", {"bolge": "guney", "donem": "2026-02"}),
         ("bati / 2026-11 / mesken", {"bolge": "bati", "donem": "2026-11", "tip": "mesken"}),
         ("merkez / 2026-02", {"bolge": "merkez", "donem": "2026-02"}),
         ("kuzey / 2026-05 / mesken", {"bolge": "kuzey", "donem": "2026-05", "tip": "mesken"})]

VARLIK = kurulum()
KATALOG = katalog_yaz(VARLIK)
print(f"varlik {len(VARLIK)} , dosya {sum(v['dosya'] for v in VARLIK)} , "
      f"katalog girisi {len(KATALOG)}\n")
print("varlik            sahip             anahtar             dosya  donem  sutun")
for v in VARLIK:
    print(f"{v['ad']:<17} {v['sahip']:<17} {str(v['anahtar']):<19} {v['dosya']:>4}"
          f"   {len(v['donem']):>4}   {len(v['sutun']):>4}")

print("\ngorev                       katalogsuz  kataloglu   bulunan varlik")
t1 = t2 = 0
for ad, g in GOREV:
    b1, v1 = katalogsuz_ara(VARLIK, g)
    b2, v2, _ = kataloglu_ara(VARLIK, KATALOG, g)
    t1, t2 = t1 + b1, t2 + b2
    print(f"{ad:<27} {b1:>10}  {b2:>9}   {v1}")
print(f"{'toplam':<27} {t1:>10}  {t2:>9}")
varlik 12 , dosya 119 , katalog girisi 12

varlik            sahip             anahtar             dosya  donem  sutun
ambar_merkezi     merkez ekibi      ('donem',)             6      6      5
pazar_bati        bati raporlama    ('donem',)            11     11      4
pazar_dogu        dogu raporlama    ('donem',)            11     11      4
pazar_guney       guney raporlama   ('donem',)            11     11      4
pazar_kuzey       kuzey raporlama   ('donem',)            11     11      4
pazar_merkez      merkez raporlama  ('donem',)            11     11      4
pazar_tarife      tarife ekibi      ('donem',)            11     11      5
urun_bati         bati birimi       ('donem', 'tip')      22     11      5
urun_dogu         dogu birimi       ('donem',)            11     11      5
urun_guney        guney birimi      ('donem',)            11     11      5
urun_kuzey        kuzey birimi      ()                     1     11      5
urun_merkez       merkez birimi     ('tip',)               2     11      5

gorev                       katalogsuz  kataloglu   bulunan varlik
kuzey / 2026-03 / isyeri            72          7   pazar_tarife
guney / 2026-02                     39          4   pazar_guney
bati / 2026-11 / mesken              6          1   ambar_merkezi
merkez / 2026-02                    61          6   pazar_merkez
kuzey / 2026-05 / mesken           117         11   urun_kuzey
toplam                             295         29

Aradaki oran on kattır: beş arama katalogsuz 295, katalogla 29 giriş baktırıyor. Farkın kaynağı ölçek değil birimdir. Katalogsuz arama varlık başına o varlığın bütün dosyalarını açar, çünkü bir varlığın hangi dönemleri ya da hangi tarifeleri kapsadığını bilmenin başka yolu yoktur; katalogla arama varlık başına tek giriş okur. On iki varlık 119 dosya tutuyor, katalog aynı kümeyi 12 girişle anlatıyor. Katalog bir dizin değildir ve sorguyu hızlandırmaz; varlık sayısı ile dosya sayısı arasındaki oranı aramaya kazandırır.

Görevler arasındaki dağılım da okunmalıdır. En ucuz arama batı için olandır: merkezî ambar hem tarife sütununu taşır hem de o dönemi kapsar ve sıralamada ilk varlıktır. En pahalısı kuzeyin 2026-05 dönemidir: ambar saklama penceresi yüzünden düşer, beş bölge pazarı tarife sütununu taşımadığı için düşer, tarife pazarı yalnız işyerini tuttuğu için düşer ve arama on birinci varlığa kadar sürer — katalogsuz 117 dosya, katalogla 11 giriş. Bir varlığı bulmanın bedelini kümenin büyüklüğü değil, aranan şeyin sıradaki yeri belirler; katalogun yaptığı o sırayı dosya biriminden giriş birimine çevirmektir.

Katalogun Bayatlaması

Katalog yazıldığı andaki düzeni taşır. Depolama tarafı durmaz: bir pazar kaldırılır, bir birim ürününü yeniden bölümler, bir pazara saklama penceresi uygulanır. Bu üç değişiklik girişlere kendiliğinden yansımaz. Aşağıdaki koşum önce kaç girişin yanlışlandığını sayar, sonra aynı beş aramayı eski katalogla yeni küme üzerinde tekrarlar.

# Onceki blogun tanimlari surer: VARLIK, KATALOG, GOREV, varlik, TUM, SON6, TAM,
# BOLGESEL, katalogsuz_ara, kataloglu_ara.
def duzen_degisti(varliklar):
    """Katalog yazildiktan sonra depolama tarafinda olan uc degisiklik."""
    yeni = []
    for v in varliklar:
        if v["ad"] == "pazar_tarife":                 # varlik kaldirildi
            continue
        if v["ad"] == "urun_kuzey":                   # yeniden bolumlendi
            yeni.append(varlik(v["ad"], v["sahip"],
                               [k for k in TUM if k["bolge"] == "kuzey"],
                               ("donem", "tip"), TAM))
        elif v["ad"] == "pazar_guney":                # saklama penceresi daraldi
            yeni.append(varlik(v["ad"], v["sahip"],
                               [k for k in TUM if k["bolge"] == "guney"
                                and k["donem"] in SON6], ("donem",), BOLGESEL))
        else:
            yeni.append(v)
    return yeni


YENI = duzen_degisti(VARLIK)
ada_gore = {v["ad"]: v for v in YENI}
print("bayat giris   kayitli anahtar / dosya / donem   gercek anahtar / dosya / donem")
bayat = 0
for g in KATALOG:
    v = ada_gore.get(g["ad"])
    if v is not None and all(g[a] == v[a] for a in ("anahtar", "dosya", "donem")):
        continue
    bayat += 1
    gercek = ("varlik yok" if v is None
              else f"{str(v['anahtar']):<18} {v['dosya']:>3}  {len(v['donem']):>3}")
    print(f"{g['ad']:<14} {str(g['anahtar']):<18} {g['dosya']:>3}  {len(g['donem']):>3}"
          f"   {gercek}")
print(f"\n{len(KATALOG)} girisin {bayat} tanesi artik var olmayan bir duzeni gosteriyor.")

print("\ngorev                       katalogsuz  kataloglu  geri dusme  bulunan varlik")
t1 = t2 = 0
for ad, gor in GOREV:
    b1, v1 = katalogsuz_ara(YENI, gor)
    b2, v2, dus = kataloglu_ara(YENI, KATALOG, gor)
    t1, t2 = t1 + b1, t2 + b2
    print(f"{ad:<27} {b1:>10}  {b2:>9}  {'evet' if dus else 'hayir':>10}   {v2}")
print(f"{'toplam':<27} {t1:>10}  {t2:>9}")
bayat giris   kayitli anahtar / dosya / donem   gercek anahtar / dosya / donem
pazar_guney    ('donem',)          11   11   ('donem',)           6    6
pazar_tarife   ('donem',)          11   11   varlik yok
urun_kuzey     ()                   1   11   ('donem', 'tip')    22   11

12 girisin 3 tanesi artik var olmayan bir duzeni gosteriyor.

gorev                       katalogsuz  kataloglu  geri dusme  bulunan varlik
kuzey / 2026-03 / isyeri           122        129        evet   urun_kuzey
guney / 2026-02                    100        104        evet   urun_guney
bati / 2026-11 / mesken              6          1       hayir   ambar_merkezi
merkez / 2026-02                    56          6       hayir   pazar_merkez
kuzey / 2026-05 / mesken           122         11       hayir   urun_kuzey
toplam                             406        251

Üç değişiklik on iki girişin üçünü yanlışladı ve üçü aynı türden değil. urun_kuzey girişi hâlâ var olan bir varlığı gösteriyor; yanlış olan yalnız kayıtlı anahtar ile dosya sayısı, bir yerine yirmi iki. Bu giriş aramayı bozmuyor, maliyet kestirimini bozuyor: o varlığa gideceğini bilen bir taraf bir dosyaya dokunacağını sanıyor. pazar_guney girişi on bir dönem vaat ediyor, varlık altı dönem taşıyor. pazar_tarife girişi hiç olmayan bir varlığı gösteriyor. Bir katalog girişinin yeşil olması o düzenin ölçüldüğü anlamına gelmez, ve yanlışlığın üç ayrı derecesi vardır: eksik kestirim, eksik kapsam, hiç yokluk.

Son tablo bunun aramaya ne yaptığını gösteriyor. Katalog toplamda hâlâ kazandırıyor, 406’ya karşı 251. Ama iki satırda kazanç eksiye dönüyor. Kuzeyin 2026-03 araması yedi giriş tarıyor, ölü girişe gidiyor, varlığı bulamıyor ve baştan tam taramaya düşüyor: 129, oysa katalog hiç olmasa 122. Güneyin 2026-02 araması dört giriş tarıyor, girişin vaat ettiği dönemi varlıkta bulamıyor ve aynı yolu izliyor: 104, katalogsuz 100. Fark küçük ama işareti önemlidir; bayat bir giriş aramanın önüne bir yanlış adres koyar ve o adres denenmeden elenemez. Kataloğun bedeli girişleri yazmak değil, girişleri düzenle aynı hızda tazelemektir.

Özet

  • Meta veri kataloğu varlık başına tek giriş tutar: ad, sahip, bölüm anahtarı, dosya sayısı, sütunlar ve kapsanan dönem ile bölge. Bir dizin değildir; sorguyu değil aramayı ucuzlatır.
  • On iki varlık ve 119 dosyalık kümede beş arama katalogsuz 295, katalogla 29 giriş baktırır; kazanç varlık sayısı ile dosya sayısı arasındaki orandan gelir.
  • Bir aramanın bedelini kümenin büyüklüğü değil aranan varlığın sıradaki yeri belirler: en ucuz arama 6’ya karşı 1, en pahalı arama 117’ye karşı 11 giriş bakar.
  • Üç değişiklik on iki girişin üçünü yanlışlar ve üç ayrı derecede: eksik kestirim (dosya sayısı 1 yerine 22), eksik kapsam (on bir dönem yerine altı) ve hiç yokluk.
  • Bayat katalogla aynı beş arama 406’ya karşı 251 giriş baktırır, ama iki arama katalogsuz olandan pahalıya biter: 129’a karşı 122 ve 104’e karşı 100.
  • Kataloğun bedeli girişleri yazmak değil, girişleri düzenle aynı hızda tazelemektir; tazelenmeyen giriş aramanın önüne yanlış bir adres koyar.

Sonraki Adım

Altı derste verinin nerede durduğu ayrıldı: şemaya uyan yer ile ham yer, ikisini bir arada tutan düzen, alt küme çıkarmanın kazandırdığı ve çoğalttığı, sahipliğin dağıtılmasının iki sayısı ve varlığı bulmanın giriş cinsinden bedeli. Bütün bu ölçümlerin ortak bir sessiz varsayımı vardı: satır hep aynı biçimde duruyordu — abone, dönem, bölge, tarife ve tüketim yan yana, tek bir düz sıra hâlinde. O biçim hiç sorgulanmadı. Oysa bir dosyaya yazılan şey bir satır listesi değil, bir tablo şeklidir; hangi alanların ölçüm hangilerinin niteleme olduğu, aynı nitelemenin kaç kez tekrarlandığı ve bir niteleme zaman içinde değiştiğinde eski değerinin saklanıp saklanmadığı ayrı kararlardır. Sonraki konu bu kararları ölçer: aynı veri, aynı yer, farklı şekil.

İ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