İçeriğe geç
academia.sh

Ders 04 / 12

Veri Pazarı

Tek bir birime adanmış bir alt küme ayrı yazıldığında sorgu maliyetinin ne olduğunun ve aynı satırın kaç yerde durduğunun sayılması: üç soruluk bir kümede bölümlemesiz ambar 13.560, en iyi merkezî düzen 3.256, iki pazar 2.580 ödüyor ve pazarın kazancı bölge sorusunda sıfır, tip sorusunda 676. Bedel çoğalmadır: altı pazar 3.322 satır daha saklıyor, satır başına 2,51 kopya, 1.122 satır üç ayrı yerde duruyor. Geç gelen kayıt ambara işlendiğinde yenilenmemiş altı pazar 126 (satır, yer) çiftinde ayrışıyor ve yarı yenilenmiş bir kümede beş bölge pazarının toplamı 4.707, ambarınki 5.340 çıkıyor.

İçindekiler

Önceki üç ders depolamanın ne sakladığını ayırdı: şemaya uyan satırı, ham satırı ve ikisini aynı yerde tutan düzeni. Üçünde de sorulan soru “bu satır nasıl saklanır” idi ve yanıt bir yazma kararıydı. Bir soru hiç sorulmadı: bu satır kimin için saklanır. Bölge sorumlusunun sorduğu soru ile tarife sorumlusunun sorduğu soru aynı satırlara dokunur, fakat aynı düzeni istemez.

Bu dersin ölçtüğü şey o ayrışmanın bedelidir. Tek bir birimin sorularına adanmış alt küme ambardan çıkarılıp ayrı yazıldığında sorgu maliyeti düşer; karşılığında aynı satır birden çok yerde durur ve o yerler ayrı ayrı tazelenir. İki sayı yan yana konur: alt kümenin kazandırdığı maliyet ve aynı satırın kaç kopyası olduğu.

  • DY41. Kaynak, hat ve depolama düzeni kurgudur ve ders içinde tanımlanır. Hiçbir ambar, göl, dosya biçimi, katalog ürünü ya da sorgu motoru çağrılmaz. Tohum 20260218.
  • DY42. Veri pazarı (data mart), ambardaki satırların tek bir alan değeri üzerinden çıkarılmış ve ayrı yazılmış alt kümesidir. Türetme kuralı tek alan üzerinde eşitliktir; özetleme yoktur, satırlar ambardaki satırların aynısıdır.
  • DY43. Maliyet ölçüsü kurs boyunca aynıdır: dosya x 120 + okunan hücre. Dosya sabiti 120 bir seçimdir; bu derste sabit tutulur, süpürülmesi sonraki derse bırakılır.
  • DY44. Bir pazar yazıldığı anın satırlarını taşır. Tazeleme ayrı bir iştir ve ambarın tazelenmesiyle aynı anda olmak zorunda değildir.
  • DY45. Bölümleme, parçalama ve çoğaltma yordamı Veritabanları müfredatındaki İlişkisel Veritabanı Yönetimi kursunda ve Sistem Tasarımı ve Dağıtık Sistemler müfredatındaki Veri Katmanı Ölçekleme kursunda ölçüldü; burada tekrarlanmaz. Bu ders yalnız alt küme çıkarma kararının sorguya ödettiğini sayar.
  • DY46. Satır oranı basılacaksa çözünürlük yazılır: küme 2.200 satırdır, oran adımı 0,0005. Maliyet bir orandır değil tam sayıdır ve değerin kendisi yazılır.

Alt Kümenin Kattığı

Ölçüm üç soruyla yapılır. İkisi bir bölgenin sorusudur: o bölgenin bir dönemi ve o bölgenin bütün dönemleri. Üçüncüsü bir tarife sorusudur: bir dönemdeki işyeri aboneleri. Üç soru da aynı 2.200 satırın üstündedir ve üçü de aynı yanıtı vermek zorundadır; ayrıldıkları tek yer, o yanıta ulaşmak için dokunulan dosya ve okunan hücredir.

# KURGUDUR. Olcum aginin sayac okumalari, hat ve depolama duzeni ders icinde
# tanimlanir; hicbir ambar, gol, dosya bicimi 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


SUTUN = ("abone", "donem", "bolge", "tip", "endeks", "birim", "m3")
DOSYA_SABIT = 120          # bir dosyaya dokunmanin sabit bedeli , hucre cinsinden


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


def yaz(kayitlar, bolumleme=()):
    """Kayitlari bolumleme anahtarina gore dosyalara dagitir."""
    duzen = {}
    for k in kayitlar:
        duzen.setdefault(tuple(k[a] for a in bolumleme), []).append(k)
    return duzen


def sorgu(duzen, bolumleme, secilen, suzgec=None, sutunlu=True):
    """Bolumleme anahtarindaki alan dosya budar , obur alan dosyanin tamamini okutur."""
    suzgec = {} if suzgec is None else suzgec
    budayan = {a: v for a, v in suzgec.items() if a in bolumleme}
    kalan = {a: v for a, v in suzgec.items() if a not in bolumleme}
    dosya, hucre, satir = 0, 0, 0
    okunan_sutun = len(secilen) if sutunlu else len(SUTUN)
    for anahtar, kayit in duzen.items():
        if budayan:
            es = dict(zip(bolumleme, anahtar))
            if any(es[a] != v for a, v in budayan.items()):
                continue
        dosya += 1
        hucre += len(kayit) * okunan_sutun
        satir += sum(1 for k in kayit if all(k[a] == v for a, v in kalan.items()))
    return {"dosya": dosya, "hucre": hucre, "eslesen_satir": satir,
            "maliyet": dosya * DOSYA_SABIT + hucre}


def pazar(kayitlar, alan, deger):
    """Birim odakli alt kume: ambardan tek bir degere ait satirlar ayri yazilir."""
    return [k for k in kayitlar if k[alan] == deger]


TUM = hattan(kaynak_uret())
SEC = ("abone", "m3")
SORU = [("dogu/07", {"bolge": "dogu", "donem": "2026-07"}),
        ("dogu/tum", {"bolge": "dogu"}),
        ("isyeri/07", {"tip": "isyeri", "donem": "2026-07"})]
DUZEN = [("bolumlemesiz", ()), ("donem", ("donem",)), ("donem+bolge", ("donem", "bolge")),
         ("donem+bolge+tip", ("donem", "bolge", "tip"))]

print(f"hattan cikan satir {len(TUM)} , dosya sabiti {DOSYA_SABIT} hucre")
print("\nmerkezi ambar     dosya   " + "  ".join(f"{a:>10}" for a, _ in SORU) + "   toplam")
for ad, bl in DUZEN:
    d = yaz(TUM, bl)
    m = [sorgu(d, bl, SEC, f)["maliyet"] for _, f in SORU]
    print(f"{ad:<17} {len(d):>5}   " + "  ".join(f"{x:>10}" for x in m) + f"   {sum(m):>6}")

p_bolge = yaz(pazar(TUM, "bolge", "dogu"), ("donem",))
p_tip = yaz(pazar(TUM, "tip", "isyeri"), ("donem",))
m = [sorgu(p_bolge, ("donem",), SEC, {"donem": "2026-07"})["maliyet"],
     sorgu(p_bolge, ("donem",), SEC, {})["maliyet"],
     sorgu(p_tip, ("donem",), SEC, {"donem": "2026-07"})["maliyet"]]
print(f"{'iki pazar':<17} {len(p_bolge) + len(p_tip):>5}   "
      + "  ".join(f"{x:>10}" for x in m) + f"   {sum(m):>6}")
hattan cikan satir 2200 , dosya sabiti 120 hucre

merkezi ambar     dosya      dogu/07    dogu/tum   isyeri/07   toplam
bolumlemesiz          1         4520        4520        4520    13560
donem                11          520        5720         520     6760
donem+bolge          55          188        2068        1000     3256
donem+bolge+tip     110          308        3388         804     4500
iki pazar            22          188        2068         324     2580

Tablonun ilk satırı taban çizgisidir: bölümlemesiz, satırlı, tarihçesiz düzende üç soru da aynı tek dosyayı baştan sona okur ve toplam 13.560 öder. Pazar kurulumu 2.580 ile en ucuzudur ve bunu yirmi iki dosyayla yapar; en iyi merkezî düzen olan donem+bolge elli beş dosyayla 3.256 öder. Ancak asıl okunması gereken yer toplam değil, sütunlardır.

Bölge sorularında pazarın kazancı sıfırdır. dogu/07 hem donem+bolge düzeninde hem doğu pazarında 188, dogu/tum ikisinde de 2.068. Bunun nedeni açıktır: bir bölge pazarı, bölge alanını bölüm anahtarına eklemekle aynı budamayı yapar. Aynı sonucu veren iki yoldan biri satırları kopyalar, öbürü yalnızca dizilişi değiştirir. Bir alt küme çıkarma kararının bölümleme kararından farklı bir şey kazandırdığı iddia ediliyorsa, o farkın sayısı gösterilmelidir.

Fark üçüncü sütunda görünür. isyeri/07 sorusunda donem+bolge düzeni 1.000, işyeri pazarı 324 öder; kazanç 676. Merkezî düzen bu soruyu ucuzlatamaz, çünkü bölüm anahtarı tek bir sıralamadır ve o sıralama bölgeye ayrılmıştır. Üçüncü alanı da anahtara eklemek işi düzeltmez, kötüleştirir: donem+bolge+tip düzeni yüz on dosyaya çıkar ve toplamı 3.256’dan 4.500’e taşır, üstelik ilk iki soruda da pahalılaşır. Okunan hücre azalırken dosya sabitinin yüz on kez ödenmesi kazancı yutar. Pazarın gerçek kazandırdığı şey budur: her alt kümenin kendi bölüm anahtarını seçebilmesi. Tek bir düzende bu mümkün değildir.

Aynı Satır Kaç Yerde Duruyor

Kazanç bir yazma kararıyla alındı ve her yazma kararı bir kopya üretti. Şimdi sayılacak olan kopyanın kendisidir. Kurulum genişletilir: beş bölge pazarı ve bir tarife pazarı, ambarın yanında. Ardından üretici tarafında bir kaza olur — bir dönemde kırk abonenin okuması geç gelir — ve kayıt sonradan ambara işlenir. Pazarların tazelenmesi ayrı bir iştir; tazelenmedikleri sürece ne söyledikleri sayılır.

# Onceki blogun tanimlari surer: hattan, kaynak_uret, pazar, TUM, BOLGE.
def gec_gelen(kayit, donem="2026-07", ust="A040"):
    """KURGU uretici kazasi: bu donemde 40 abonenin okumasi hic gelmedi."""
    return [k for k in kayit if not (k["donem"] == donem and k["abone"] <= ust)]


def anahtar(kayitlar):
    return {(k["abone"], k["donem"]) for k in kayitlar}


def toplam(kayitlar, donem="2026-07"):
    return sum(k["m3"] for k in kayitlar if k["donem"] == donem)


PAZAR = [(b, "bolge", b) for b in BOLGE] + [("isyeri", "tip", "isyeri")]
ESKI = hattan(gec_gelen(kaynak_uret()))       # gec gelen kayitla yazilmis pazarlar

kopya = {}
for k in TUM:
    n = 1 + sum(1 for _, a, d in PAZAR if k[a] == d)
    kopya[n] = kopya.get(n, 0) + 1
saklanan = len(TUM) + sum(len(pazar(TUM, a, d)) for _, a, d in PAZAR)
print(f"ambar {len(TUM)} satir , alti pazar {saklanan - len(TUM)} satir , "
      f"saklanan toplam {saklanan}")
print(f"iki yerde duran satir {kopya[2]} , uc yerde duran {kopya[3]} , "
      f"satir basina ortalama {saklanan / len(TUM):.2f} kopya")

print("\npazar     satir   yenilenmemis  eksik satir   07 ambar   07 pazar   fark")
eksik_toplam = 0
for ad, a, d in PAZAR:
    yeni, esk = pazar(TUM, a, d), pazar(ESKI, a, d)
    eksik = len(anahtar(yeni) - anahtar(esk))
    eksik_toplam += eksik
    print(f"{ad:<9} {len(yeni):>5}   {len(esk):>12}   {eksik:>10}   {toplam(yeni):>8}"
          f"   {toplam(esk):>8}   {toplam(yeni) - toplam(esk):>5}")
print(f"tutarsiz (satir , yer) cifti: {eksik_toplam}")

# Kismi yenileme: ambar ve iki bolge pazari yenilendi , uc pazar yenilenmedi.
YENI = {"dogu", "bati"}
pazar_toplami = sum(toplam(pazar(TUM if b in YENI else ESKI, "bolge", b)) for b in BOLGE)
print(f"\nambarin 2026-07 toplami {toplam(TUM)} , bes bolge pazarinin toplami "
      f"{pazar_toplami} , fark {toplam(TUM) - pazar_toplami}")
ambar 2200 satir , alti pazar 3322 satir , saklanan toplam 5522
iki yerde duran satir 1078 , uc yerde duran 1122 , satir basina ortalama 2.51 kopya

pazar     satir   yenilenmemis  eksik satir   07 ambar   07 pazar   fark
dogu        374            356           18        958        665     293
bati        341            333            8        812        674     138
kuzey       506            492           14       1251       1041     210
guney       440            418           22       1039        780     259
merkez      539            521           18       1280       1116     164
isyeri     1122           1076           46       2738       2113     625
tutarsiz (satir , yer) cifti: 126

ambarin 2026-07 toplami 5340 , bes bolge pazarinin toplami 4707 , fark 633

Birinci sayı saklama tarafındadır: 2.200 satırlık bir veri kümesi altı pazarla birlikte 5.522 satır olarak duruyor, satır başına 2,51 kopya. Beş bölge pazarı satırları ayrıştırdığı için her satırı tam bir kez çoğaltıyor; tarife pazarı bunun üstüne biniyor ve 1.122 satırı üçüncü bir yere yazıyor. Kopya sayısı düzenlerin sayısıyla değil, düzenlerin kesişmesiyle artar; kesişmeyen beş pazar ikinci kopyayı, kesişen bir pazar üçüncüyü getirdi.

İkinci sayı tutarlılık tarafındadır ve saklama sayısından daha ağırdır. Geç gelen kayıt ambara işlendiğinde ambar 2.200 satıra çıkıyor, tazelenmemiş pazarlar yazıldıkları andaki satırlarda kalıyor. Ayrışma 126 (satır, yer) çiftindedir: seksen satır beş bölge pazarında, kırk altısı ayrıca tarife pazarında eksik. Ayrışmanın sunulan sayıya yansıması sütunlardadır — doğu pazarı o dönem için 665 diyor, ambar 958 diyor. Aynı soruya iki adres iki yanıt veriyor ve hiçbir yerde hata görünmüyor; her iki taraf da kendi içinde tutarlı, eksiksiz ve tür bakımından kusursuz.

Üçüncü sayı çoğalmanın en sinsi biçimidir. Tazeleme hepsi için aynı anda yapılmaz; ambar ve iki bölge pazarı yenilenmiş, üçü yenilenmemiş bir anda beş bölge pazarının toplamı 4.707, ambarın aynı dönem toplamı 5.340 çıkıyor. Fark 633 m3 ve iki sayı da bir kaynağın kendi içinde doğru okumasıdır. Ambar bölge pazarlarının birleşimi olduğu hâlde birleşimin toplamı ambarınkini vermiyor; veren şey tazelemenin sırası. Bir alt küme çıkarıldığında ölçülmesi gereken üçüncü sayı, iki adresin ne kadar süre farklı yanıt verdiğidir.

Özet

  • Veri pazarı, ambardaki satırların tek bir alan değeri üzerinden çıkarılmış ve ayrı yazılmış alt kümesidir; özet değil, aynı satırların ikinci bir kopyasıdır.
  • Üç soruluk kümede bölümlemesiz taban 13.560, en iyi merkezî düzen 3.256, iki pazar 2.580 öder; ama pazarın bölge sorularındaki kazancı sıfırdır, çünkü orada bölüm anahtarına bir alan eklemekle aynı budama elde edilir.
  • Pazarın gerçek kazancı her alt kümenin kendi bölüm anahtarını seçebilmesidir: tarife sorusunda merkezî düzen 1.000, tarife pazarı 324 öder; üçüncü alanı merkezî anahtara eklemek toplamı 3.256’dan 4.500’e çıkarır.
  • Bedel çoğalmadır: altı pazar 3.322 satır daha saklar, satır başına 2,51 kopya, 1.122 satır üç ayrı yerde durur. Kopya sayısını düzenlerin sayısı değil kesişmesi belirler.
  • Tazeleme ayrıştığında 126 (satır, yer) çifti ayrışır ve aynı soru iki adreste iki yanıt verir (665 ve 958) — hiçbir hata görünmeden.
  • Yarı yenilenmiş bir kümede beş bölge pazarının toplamı 4.707, ambarın aynı dönem toplamı 5.340 olur; iki sayı da kendi kaynağında doğrudur.

Sonraki Adım

Bu derste alt kümeyi kimin çıkardığı hiç sorulmadı. Altı pazarın bölüm anahtarını, tazeleme sırasını ve türetme kuralını tek bir taraf belirledi; bölge sorumlusu yalnızca kendisi için yazılmış alt kümeyi okudu. Karar o tarafta kalmasaydı ne olurdu — düzen kararını bölgenin kendisi verseydi, tazeleme takvimini kendisi seçseydi. İki sayı bu soruyla değişir: düzen kararı alan taraf sayısı ve uçtan uca bir sorgunun dokunduğu düzen sayısı. Sonraki ders sahipliğin dağıtıldığı iki modeli bu iki sayıyla ölçer ve aynı yerde bu kursun her maliyetinin dayandığı dosya sabitini süpürerek hangi sonuçların o sabite bağlı olduğunu gösterir.

İ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