Ders 10 / 12
Sütunlu Dosya Biçimleri
Seçici okumanın ve sıkıştırmanın okunan hücre üzerinden sayılması: iki sütun seçildiğinde sütunlu okuma 400 hücre ve 520 maliyet, satırlı okuma 1400 hücre ve 1520 maliyet veriyor; seçilen sütun sayısı arttıkça fark 200'er hücre kapanıyor ve yedinci sütunda tam olarak sıfırlanıyor, yani sütunlu biçimin kazancı sorgunun okumadığı sütun kadar. Sıkıştırma okunan hücre üzerinden modellendiğinde bu kapanma noktası tablodan çıkıyor: yedi sütunun tamamı sütunlu düzende 851, satırlı düzende 1400 hücre. Kazanç ayrık değer sayısının değil koşu sayısının işi; bölge sütunu beş ayrık değer taşırken 158 koşu veriyor. Dosya içi sıralama tek bir sorgu için seçilir: bölge ile tipe göre sıralamak o sorguyu 253 hücreden 15'e indiriyor ama metreküp sütununu 196'dan 200'e, yani sıkıştırmasız değere geri çıkarıyor.
İçindekiler
Önceki üç ders tablonun şeklini tartıştı: olgu ile boyutun ayrılması, normalleştirme derecesinin birleştirmeye ödettiği, tarihçe tutmayan boyutun cevabı sessizce yanlışlaması. Üçünde de tablo mantıksal bir nesne olarak durdu — satırları, sütunları ve bir sonucu olan bir küme. Bir şey hiç sorulmadı: bu tablo diske indiğinde ne yan yana duruyor, satırlar mı sütunlar mı.
Bu dersin ölçtüğü şey o karardır. Ölçü değişmez: dokunulan dosya, okunan hücre ve maliyet. Değişen tek şey, aynı sorgunun aynı dosyadan kaç hücre okumak zorunda kaldığıdır. İki soru sırayla yanıtlanır. Seçici okuma ne kazandırıyor ve bu kazanç nerede biter; sıkıştırma o sınırı nereye taşır.
- AM41. Kaynak, hattan çıkan tüketim satırları ve dosya düzeni kurgudur ve ders içinde üretilir. Hiçbir ambar, göl, dosya biçimi ya da sorgu motoru çağrılmaz. Tohum 20260218.
- AM42. Sütunlu dosya biçimi (columnar file format) ve satırlı dosya biçimi (row-oriented file format) birer sınıf adıdır. Ayrım tek bir davranıştadır: sütunlu okuma yalnız seçilen sütunları alır, satırlı okuma kaydın tamamını alır.
- AM43. Kayıt yedi sütun taşır. Okunan hücre, dokunulan satır ile okunan sütunun çarpımıdır.
- AM44. Maliyet, dosya sayısı ile dosya sabiti 120’nin çarpımına okunan hücrenin eklenmesidir. Sabit bir seçimdir; bu derste iki düzen de aynı tek dosyaya dokunduğu için sabit farkın dışında kalır.
- AM45. Sıkıştırma okunan hücre üzerinden modellenir, algoritma yazılmaz. Bir sütunun sıkışmış bedeli o sütundaki koşu (run) sayısıdır: dosya sırasında ardışık duran aynı değerler tek hücreye iner. Sıkıştırma yordamı Linux ve Sistem Yönetimi müfredatındaki Linux’a Giriş kursunda ölçüldü; tekrarlanmaz.
- AM46. Satırlı düzende koşu birimi kaydın tamamıdır. Abone ile dönem çiftleri tekil olduğu için ardışık iki kayıt hiçbir zaman eşit değildir ve daralma olmaz.
- AM47. Dosya içi sıralama bir yazma kararıdır ve dosya başına tek olabilir.
- AM48. Bölüm anahtarı bu derste sabittir ve
donem’dir. Anahtarın kendisi sonraki dersin konusudur.
Seçici Okumanın Ödettiği
Sorgu tek bir dönemin bölge bazlı tüketimini istiyor; ihtiyacı olan iki sütun var, bolge ve
m3. Aşağıdaki blok hattı, düzeni ve maliyet ölçüsünü kurar, sonra aynı sorguyu seçilen sütun
sayısını birden yediye çıkararak süpürür.
# KURGUDUR. Olcum aginin sayac okumalari , tuketim satirlari ve dosya duzeni ders # icinde uretilir; 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)] SUTUN = ("abone", "donem", "bolge", "tip", "endeks", "birim", "m3") DOSYA_SABIT = 120 # bir dosyaya dokunmanin sabit bedeli , hucre cinsinden 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 satirlar(): """Hattan cikan tuketim satirlari. Saglam kaynakta ayikla ve tekille asamalari satir dusurmedigi icin tuketim dogrudan kaynaktan , donem farkiyla hesaplanir.""" ham = [] 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) ham.append({"abone": ab, "donem": d, "bolge": a["bolge"], "tip": a["tip"], "endeks": e, "birim": "m3"}) tablo, cikti = {(k["abone"], k["donem"]): k for k in ham}, [] for k in ham: i = DONEM.index(k["donem"]) onceki = tablo.get((k["abone"], DONEM[i - 1])) if i else None if onceki is not None: cikti.append(dict(k, m3=k["endeks"] - onceki["endeks"])) return cikti def yaz(kayitlar, bolumleme=()): """Satirlari 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): """Dokunulan dosya , okunan hucre ve maliyet = dosya x DOSYA_SABIT + hucre. Sutunlu okuma yalniz secilen sutunlari , satirli okuma kaydin tamamini alir.""" suzgec = {} if suzgec is None else suzgec budayan = {a: v for a, v in suzgec.items() if a in bolumleme} dosya, hucre = 0, 0 genislik = 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) * genislik return {"dosya": dosya, "hucre": hucre, "maliyet": dosya * DOSYA_SABIT + hucre} SATIR = satirlar() DUZEN = yaz(SATIR, ("donem",)) EKLEME = ["bolge", "m3", "abone", "tip", "birim", "endeks", "donem"] print(f"hattan cikan satir {len(SATIR)} , donem duzeninde dosya {len(DUZEN)} ," f" dosya basina satir {len(SATIR) // len(DUZEN)}") print("\nsecilen sutun sutunlu hucre maliyet satirli hucre maliyet fark") for n in range(1, len(SUTUN) + 1): sec = tuple(EKLEME[:n]) a = sorgu(DUZEN, ("donem",), sec, {"donem": "2026-07"}, True) b = sorgu(DUZEN, ("donem",), sec, {"donem": "2026-07"}, False) print(f"{n:>13} {a['hucre']:>13} {a['maliyet']:>7} {b['hucre']:>13}" f" {b['maliyet']:>7} {b['maliyet'] - a['maliyet']:>4}")
hattan cikan satir 2200 , donem duzeninde dosya 11 , dosya basina satir 200
secilen sutun sutunlu hucre maliyet satirli hucre maliyet fark
1 200 320 1400 1520 1200
2 400 520 1400 1520 1000
3 600 720 1400 1520 800
4 800 920 1400 1520 600
5 1000 1120 1400 1520 400
6 1200 1320 1400 1520 200
7 1400 1520 1400 1520 0
İkinci satır dersin başlangıç sayısıdır. Aynı dosyaya, aynı 200 satıra, aynı süzgeçle dokunan iki düzenden biri 400 hücre okuyup 520 ödüyor, öbürü 1400 hücre okuyup 1520 ödüyor. Hiçbiri daha akıllı değildir; biri sorgunun istemediği beş sütunu almak zorundadır, öbürü değildir.
Tablonun asıl bulgusu sağdaki iki sütunun sabitliğidir. Satırlı okuma 1400 hücrede durur ve seçilen sütun sayısına hiç tepki vermez, çünkü kaydın tamamını zaten ilk sorguda almıştır. Sütunlu okuma her eklenen sütunla tam 200 hücre büyür. Fark bu yüzden düzenli iner: 1200, 1000, 800, 600, 400, 200 ve yedinci sütunda 0.
Kapanma noktası bir eşik değil, bir tanımdır. Sütunlu biçimin kazandırdığı şey sorgunun okumadığı sütun sayısıdır, ne eksik ne fazla. Yedinci sütunda kazanç sıfırlanır, çünkü orada sorgu zaten kaydın tamamını istemektedir. Bir düzenin “sütunlu olduğu için hızlı” diye anılması bu tablonun okunmadığı anlamına gelir: iki sütun okuyan sorgu için doğru, yedi sütun okuyan sorgu için yanlıştır.
Dosya sabitinin bu tabloda payı yoktur. İki düzen de tek dosyaya dokunduğu için maliyetin sabit parçası ikisinde de 120’dir ve maliyet farkı hücre farkına birebir eşittir. Sabit 60 ya da 480 olsaydı sağdaki sütun değişmezdi. Bu, sabite duyarsız bir sonuçtur ve sonraki derste tersi görülür.
Sıkıştırma Okunan Hücre Üzerinden Ölçülür
Yukarıdaki model her hücreyi bir birim sayar. Sütunlu düzenin ikinci kazancı buradadır: bir sütunun bütün değerleri bitişik durduğu için ardışık tekrarlar tek hücreye inebilir. Aşağıdaki blok bu daralmayı koşu sayısıyla ölçer ve dosyanın yedi sütununu tek tek sayar.
# Bu blok ilk bloktaki SUTUN , DOSYA_SABIT , satirlar() ve yaz() tanimlarini surdurur. def kosu(degerler): """Ardisik ayni degerlerin olusturdugu blok sayisi.""" n, onceki = 0, object() for d in degerler: if d != onceki: n += 1 onceki = d return n def sik_hucre(kayit, secilen, sutunlu=True): """Sikismis okuma , hucre cinsinden. Sutunlu duzende her sutun kendi icinde bitisiktir ve ardisik ayni deger tek hucreye iner; satirli duzende kayit butun olarak durur , iki kaydin anahtari ayni olmadigi icin daralma olmaz.""" if not sutunlu: return len(kayit) * len(SUTUN) return sum(kosu([k[s] for k in kayit]) for s in secilen) DOSYA = yaz(satirlar(), ("donem",))[("2026-07",)] print(f"tek dosya , donem 2026-07 , satir {len(DOSYA)}") print("\nsutun ayrik deger kosu sikismamis sikismis") for s in SUTUN: print(f"{s:<9} {len(set(k[s] for k in DOSYA)):>11} {kosu([k[s] for k in DOSYA]):>4}" f" {len(DOSYA):>10} {kosu([k[s] for k in DOSYA]):>8}") ham, sik = len(DOSYA) * len(SUTUN), sik_hucre(DOSYA, SUTUN) sat = sik_hucre(DOSYA, SUTUN, False) print(f"\nyedi sutun , sutunlu sikismamis: hucre {ham} , maliyet {ham + DOSYA_SABIT}") print(f"yedi sutun , sutunlu sikismis : hucre {sik} , maliyet {sik + DOSYA_SABIT}") print(f"yedi sutun , satirli : hucre {sat} , maliyet {sat + DOSYA_SABIT}")
tek dosya , donem 2026-07 , satir 200 sutun ayrik deger kosu sikismamis sikismis abone 200 200 200 200 donem 1 1 200 1 bolge 5 158 200 158 tip 2 95 200 95 endeks 200 200 200 200 birim 1 1 200 1 m3 46 196 200 196 yedi sutun , sutunlu sikismamis: hucre 1400 , maliyet 1520 yedi sutun , sutunlu sikismis : hucre 851 , maliyet 971 yedi sutun , satirli : hucre 1400 , maliyet 1520
Önceki bölümün kapanma noktası bu blokla tablodan çıkar. Yedi sütunun tamamını okuyan sorgu sütunlu düzende 851 hücre, satırlı düzende 1400 hücre okur; maliyet 971’e karşı 1520’dir. Seçici okumanın kazancı bittiği yerde sıkıştırmanın kazancı sürer ve fark 549 hücrede durur.
Koşu sütunu ile ayrık değer sütununun ayrışması dersin en yanıltıcı yeridir. bolge beş
ayrık değer taşır, buna karşın 158 koşu verir: dosya abone sırasında yazıldığı için beş
değer iki yüz satıra serpilmiştir ve neredeyse hiç ardışık tekrar yoktur. donem ile birim
tek değer taşır ve 1 hücreye iner; ikisi de dosya boyunca değişmez. Sıkışan şey az sayıda
farklı değer değil, yan yana duran aynı değerdir.
abone ile endeks sütunları bunun karşı ucudur. İkisi de satır başına tekil olduğu için
200 koşu verir ve sıkışmamış değerle birebir aynı kalır. Bu iki sütunu okuyan bir sorgu
sütunlu düzende hiçbir sıkıştırma kazancı görmez.
Sıralama Tek Bir Sorgu İçin Seçilir
Koşu sayısı dosyanın yazılış sırasına bağlıdır, dolayısıyla bir yazma kararıyla değiştirilebilir. Aşağıdaki blok aynı dosyayı üç ayrı sırayla yazıp üç sorgunun okuduğu hücreyi karşılaştırır.
# Bu blok onceki iki bloktaki tanimlari surdurur. SIRALAMA = {"abone (dogal)": lambda k: (k["abone"],), "bolge , tip": lambda k: (k["bolge"], k["tip"]), "m3": lambda k: (k["m3"],)} SORGU = {"bolge+tip": ("bolge", "tip"), "m3": ("m3",), "abone+endeks": ("abone", "endeks")} DOSYA = yaz(satirlar(), ("donem",))[("2026-07",)] print("tek dosya , okunan hucre ; parantez icinde maliyet = 1 x 120 + hucre") print("\nsiralama " + "".join(f"{a:>16}" for a in SORGU) + " yedi sutun") for ad, anahtar in SIRALAMA.items(): s = sorted(DOSYA, key=anahtar) h = [sik_hucre(s, sec) for sec in SORGU.values()] + [sik_hucre(s, SUTUN)] print(f"{ad:<15} " + "".join(f"{f'{x} ({x + DOSYA_SABIT})':>16}" for x in h)) h = [len(DOSYA) * len(sec) for sec in SORGU.values()] + [len(DOSYA) * len(SUTUN)] print(f"{'sikistirmasiz':<15} " + "".join(f"{f'{x} ({x + DOSYA_SABIT})':>16}" for x in h))
tek dosya , okunan hucre ; parantez icinde maliyet = 1 x 120 + hucre siralama bolge+tip m3 abone+endeks yedi sutun abone (dogal) 253 (373) 196 (316) 400 (520) 851 (971) bolge , tip 15 (135) 200 (320) 400 (520) 617 (737) m3 252 (372) 46 (166) 400 (520) 700 (820) sikistirmasiz 400 (520) 200 (320) 400 (520) 1400 (1520)
İkinci satır kazancın en büyüğüdür. Dosya bölgeye ve tipe göre sıralandığında bu iki sütunu okuyan sorgu 253 hücreden 15 hücreye iner, maliyet 373’ten 135’e düşer. Beş bölge ile iki tip artık bitişik bloklar hâlinde durmaktadır ve on beş koşu bütün dosyayı anlatmaya yetmektedir.
Aynı satırın ikinci sütunu bu kursun ikinci iddiasını taşır: düzen de bozar. Bölgeye göre
sıralamak m3 sütununu 196 koşudan 200 koşuya çıkarır. Sayı küçüktür ama yönü nettir — o sütun
için sıralama yalnızca yararsız değil, doğal sıradan kötüdür ve sıkıştırmasız değerle
(200) birebir aynı yere oturur. Metreküp sütununu okuyan sorgu, bölge sorgusu için alınmış bir
karar yüzünden sıkıştırmanın tamamını kaybeder.
Üçüncü satır aynı takası ters yönden gösterir. Dosya metreküpe göre sıralandığında o sütun 46 hücreye iner, buna karşılık bölge ile tip 252‘de kalır, yani doğal sıradaki 253’ten ayırt edilemez. Bir dosyanın tek bir sıralaması olabilir; ikisi aynı anda seçilemez.
Son sütun kararın toplam bedelini verir: yedi sütunun tamamı doğal sırada 851, bölge sırasında 617, metreküp sırasında 700 hücre. Üç sayı da satırlı düzenin 1400’ünün altındadır, ama hangisinin seçileceği yalnızca hangi sorgunun adının yazıldığına bağlıdır. Sıralaması bir sorgu adı olmadan seçilmiş bir dosya, kursun kuralı gereği ölçülmemiştir.
Özet
- Sütunlu ve satırlı biçim arasındaki fark tek bir davranıştır: sütunlu okuma seçilen sütunları, satırlı okuma kaydın tamamını alır. İki sütunluk sorguda sütunlu düzen 400 hücre / 520 maliyet, satırlı düzen 1400 hücre / 1520 maliyet öder.
- Seçici okumanın kazancı sorgunun okumadığı sütun kadardır ve her eklenen sütunla 200 hücre erir; yedinci sütunda tam olarak sıfırlanır. İki düzen de tek dosyaya dokunduğu için dosya sabiti 120 bu farkın dışında kalır.
- Sıkıştırma okunan hücre üzerinden modellendiğinde kapanma noktası tablodan çıkar: yedi sütunun tamamı sütunlu düzende 851, satırlı düzende 1400 hücredir.
- Sıkışan şey az sayıda ayrık değer değil, yan yana duran aynı değerdir:
bolgebeş ayrık değerle 158 koşu verirkendonemtek değerle 1 koşuya iner; satır başına tekil olanaboneveendekshiç sıkışmaz. - Dosya içi sıralama bir sorgu için seçilir ve başka bir sorgunun kazancını götürür: bölge ile tipe
göre sıralamak o sorguyu 253’ten 15 hücreye indirirken
m3sütununu 196’dan 200’e, yani sıkıştırmasız değerine geri çıkarır.
Sonraki Adım
Bu dersin bütün sayıları tek bir dosyanın içinde ölçüldü. Bölüm anahtarı donem olarak
sabit tutuldu, süzgeç hep o anahtarın üstüne düştü ve her sorgu tek dosyaya dokundu; dosya sabiti
bu yüzden hiçbir farkı değiştirmedi. Anahtarın kendisi hiç sorgulanmadı. Sonraki ders bu sabiti
kaldırır ve iki soruyu sorar: süzgeç bölüm anahtarının dışında bir alana düştüğünde ne
oluyor, ve aynı veriyi daha çok dosyaya bölmek — okunan hücre hiç artmasa bile — maliyeti nereye
taşıyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.