---
title: 'Parça Parça İşleme'
source: 'https://academia.sh/tr/kurslar/python-ile-analiz/parca-parca-isleme'
course: 'Python ile Veri Analizi'
language: tr
updated: '2026-08-17T18:08:44+00:00'
license: 'CC BY-SA 4.0'
---

# Parça Parça İşleme

Kurgu ölçüm ağının 3.199 satırlık dosyası parça parça okunduğunda bellek tepesi parça boyutuyla düşer ama işlemin taşıdığı durum düşmez: 100 satırlık parçada tepe 36.132 bayt, kümenin tamamını tutmaya göre 32 kat küçüktür ve toplam dört parça boyutunda da 66.667,9 m³ çıkar. Toplam, sayım ve bölge kırılımı 3–5 öğelik durumla parça içinde biter; kesin medyan 321 kovalık histogramla, kesin farklı abone sayımı 1.329 öğelik durumla yürür ve o 87.166 bayt parça küçüldükçe küçülmez. Parçalama sessizce bir sıra varsayımı yapar: akan hesap abone sıralı dosyada 1.035 abone için sonuç verirken dönem sıralı dosyada hiç hata vermeden 0 abone için sonuç verir; parça sınırı bölgeye taşındığında parça ortalamalarının ortalaması genel ortalamadan 0,1039 m³ ayrışır.

Önceki ders bir sütunun bellek karşılığını 31 kata varan oranlarda daralttı, ama daraltmanın bir
tabanı olduğunu da söyledi: 3.199 satır her tiple sığar, kümenin kendisi büyüdükçe hiçbir tip
yetmez. Bu ders o taban aşıldığında ne yapıldığını ölçer — küme belleğe bir defada alınmaz, parça
parça okunur.

Parçalamanın vaadi açıktır: aynı anda bellekte yalnız bir parça durur ve tepe kullanım parça
boyutuyla belirlenir. Dersin ölçüsü bu vaadin karşılığını iki sayıyla okur. Birincisi **kazanç**:
parça boyutu düştüğünde bellek tepesi kaç kat küçülüyor. İkincisi **taşınan durum**: işlemin parça
dışında tuttuğu ve parça boyutu değiştiğinde küçülmeyen kalem. Bir işlemin parça parça
hesaplanabilir olup olmadığını belirleyen şey budur.

- **AB6.** Küme, önceki dersin kurgu ölçüm ağı kümesidir: 3.199 satır, 1.329 abone, üç dönem,
  toplam 66.667,9 m³. Aynı tohumla üretilir ve çıktı koşumdan koşuma aynıdır. **Modeldir.**
- **AB7.** Dosya kümenin beş alanını taşır; tarife basamağı okumadan türetildiği için dışa
  aktarıma girmez.
- **AB8.** Dosya dönem sırasında yazılır: önce 2024-01'in 1.329 satırı, sonra 2024-02'nin 1.035
  satırı, sonra 2024-03'ün 835 satırı. Bir abonenin satırları birbirinden yüzlerce satır uzaktadır.
- **AB9.** Bellek tepesi, aynı anda bellekte duran satırların ve işlem durumunun baytıdır;
  `sys.getsizeof` ile ölçülür ve sekiz baytlık göstericisi olan bir çalışma ortamına aittir.
  Değişmeyen şey oranlardır.
- **AB10.** İki ortalamanın aynı sayılması için eşik 0,05 m³'tür, çünkü okumalar bir ondalıkla
  raporlanır ve bundan küçük bir fark yalnızca yuvarlamadan gelebilir.

## Parça Boyutu ve Bellek Tepesi

```python
# kume.py — ayni kurgu olcum agi kumesi bir dosyaya yazilir. MODELDIR: gercek
# bir disa aktarim yerine ayni yapiyi ureten bir uretec yazildi; tohum gorunur
# ve cikti kosumdan kosuma aynidir. 3199 satir, 1329 abone, uc donem.
import csv, itertools, os, sys, tempfile
TOHUM = 1246
BOLGE = ("kuzey", "dogu", "merkez", "guney", "bati")
DONEM = (("2024-01", 1329), ("2024-02", 1035), ("2024-03", 835))
YOGUNLUK = (0, 1, 2, 2, 2, 3, 4, 2, 2, 1)   # merkez agirlikli kurgu olcum agi
BASLIK = ("abone_no", "sayac_no", "donem", "bolge", "okuma_m3")


def uretec(tohum: int):
    s = tohum & 0xFFFFFFFF

    def sonraki() -> float:
        nonlocal s
        s = (1103515245 * s + 12345) & 0xFFFFFFFF
        return s / 4294967296
    return sonraki


def kayitlar() -> list[tuple]:
    r, k = uretec(TOHUM), []
    for donem, adet in DONEM:
        for i in range(adet):
            k.append((10000 + i, f"S-{4000 + i}", donem,
                      BOLGE[YOGUNLUK[i % 10]], round(5 + r() * 32.0, 1)))
    return k


k0 = kayitlar()
KLASOR = tempfile.mkdtemp(prefix="olcum-")
YOL = os.path.join(KLASOR, "okuma.csv")
with open(YOL, "w", newline="") as f:
    y = csv.writer(f, lineterminator="\n")
    y.writerow(BASLIK)
    y.writerows(k0)

bayt = lambda p: sys.getsizeof(p) + sum(
    sys.getsizeof(s) + sum(sys.getsizeof(a) for a in s) for s in p)
TAM = bayt([list(map(str, s)) for s in k0])
print(f"tohum {TOHUM}; dosya {os.path.getsize(YOL)} bayt, {len(k0)} veri satiri")
print(f"kumenin tamami bellege alinirsa {TAM} bayt, satir basina "
      f"{round(TAM / len(k0))} bayt")
print(f"toplam {sum(x[4] for x in k0):.1f} m3, farkli abone {len({x[0] for x in k0})}")
```

```
tohum 1246; dosya 102548 bayt, 3199 veri satiri
kumenin tamami bellege alinirsa 1152229 bayt, satir basina 360 bayt
toplam 66667.9 m3, farkli abone 1329
```

Dosya diskte 102.548 bayt tutuyor, bellekte 1.152.229 bayt — on bir kat. Fark önceki dersin
konusudur: metin satırı çözümlendiğinde her alan ayrı bir nesne olur. Bu ders o çarpanı veri
olarak alır ve tek soruyu sorar: kümenin tamamını aynı anda bellekte tutmadan aynı sayıları
üretmek mümkün mü.

```python
# parca.py — dosya parca parca okunur. Toplam, satir sayisi, en buyuk ve bolge
# basina toplam ayni gecisde birikir; parca boyutu yalnizca ayni anda bellekte
# duran satir sayisini degistirir.
def parcalar(yol: str, n: int):
    with open(yol, newline="") as f:
        okuyucu = csv.reader(f)
        next(okuyucu)                                   # baslik satiri
        while (p := list(itertools.islice(okuyucu, n))):
            yield p


def tek_gecis(yol: str, n: int) -> dict:
    tepe = adet = sayi = 0
    toplam, enb, bolgeli = 0.0, 0.0, {}
    for p in parcalar(yol, n):
        tepe, adet = max(tepe, bayt(p)), adet + 1
        for s in p:
            o = float(s[4])
            toplam, sayi, enb = toplam + o, sayi + 1, max(enb, o)
            bolgeli[s[3]] = bolgeli.get(s[3], 0.0) + o
    return {"parca": adet, "tepe": tepe, "sayi": sayi, "toplam": round(toplam, 1),
            "enb": enb, "bolge": round(max(bolgeli.values()), 1)}


G = (14, 10, 12, 11, 8, 13, 16)
y2 = lambda h: "".join(str(v).rjust(G[j]) if j else str(v).ljust(G[0])
                       for j, v in enumerate(h))
print(y2(["parca boyutu", "parca", "tepe bayt", "tepe/tam", "gecis", "toplam m3",
          "en buyuk bolge"]))
for n in (100, 400, 1600, 3199):
    r = tek_gecis(YOL, n)
    print(y2([n, r["parca"], r["tepe"], f"{r['tepe'] / TAM:.3f}", 1, r["toplam"],
              r["bolge"]]))
print(f"parca 100 iken tepe, kumenin tamamini tutmaya gore "
      f"{round(TAM / tek_gecis(YOL, 100)['tepe'])} kat kucuk; dort kosumda da "
      f"toplam {tek_gecis(YOL, 100)['toplam']} m3 ve satir {tek_gecis(YOL, 100)['sayi']}")
```

```
parca boyutu       parca   tepe bayt   tepe/tam   gecis    toplam m3  en buyuk bolge
100                   32       36132      0.031       1      66667.9         33462.3
400                    8      144085      0.125       1      66667.9         33462.3
1600                   2      577624      0.501       1      66667.9         33462.3
3199                   1     1152229      1.000       1      66667.9         33462.3
parca 100 iken tepe, kumenin tamamini tutmaya gore 32 kat kucuk; dort kosumda da toplam 66667.9 m3 ve satir 3199
```

Kazanç doğrusaldır ve tabloda okunur: parça boyutu 3.199'dan 100'e indiğinde tepe 1.152.229
bayttan 36.132 bayta, kümenin otuz ikide birine düşer. Geçiş sayısı dört koşumda da birdir; dosya
bir kez okunur. Toplam da dört koşumda aynı çıkar — 66.667,9 m³ — ve en büyük bölgenin toplamı
33.462,3 m³'te sabit kalır. Bu dört işlem parça boyutuna karşı **kayıtsızdır**: her biri sabit
sayıda birikeç tutar ve parçadan parçaya yalnız o birikeçler geçer.

Parça boyutunun bedeli tabloda görünmüyor, çünkü bu derste süre ölçülmüyor. Küçük parça daha çok
çağrı, büyük parça daha çok bellek demektir; seçim bu iki sayı arasındadır ve tepe sınırı
donanımdan gelir. Ölçülebilir olan taraf tepe baytıdır ve o parça boyutuyla orantılı çıkar.

## Hangi İşlem Parça İçinde Biter

```python
# islem.py — hangi islem parca icinde biter, hangisi parca disinda durum tasir.
# Olcu: parca boyutundan bagimsiz olarak tasinan durum ogesi ve baytidir.
ESIK = 0.05   # okumalar bir ondalikla raporlanir, altindaki fark yuvarlamadandir
N = 400
sutun, bolgeli, aboneler, kova = [], {}, {}, {}
for p in parcalar(YOL, N):
    for s in p:
        o = float(s[4])
        sutun.append(o)
        bolgeli[s[3]] = bolgeli.get(s[3], 0.0) + o
        aboneler[s[0]] = o
        d = round(o * 10)                 # okumalar bir ondalikli: 321 kova yeter
        kova[d] = kova.get(d, 0) + 1
birikim, medyan_hist = 0, None
for d in sorted(kova):
    birikim += kova[d]
    if medyan_hist is None and birikim >= (len(sutun) + 1) // 2:
        medyan_hist = d / 10

olcu = lambda x: sys.getsizeof(x) + sum(sys.getsizeof(a) for a in x)
G2 = (32, 12, 12, 8, 12)
y3 = lambda h: "".join(str(v).rjust(G2[j]) if j else str(v).ljust(G2[0])
                       for j, v in enumerate(h))
print(y3(["islem", "durum ogesi", "durum bayt", "gecis", "sonuc"]))
for ad, durum, bayt_d, sonuc in [
        ("toplam, sayi, en buyuk", 3, 3 * 24, round(sum(sutun), 1)),
        ("agirlikli ortalama", 2, 2 * 24, round(sum(sutun) / len(sutun), 4)),
        ("bolge basina toplam", len(bolgeli), olcu(bolgeli), len(bolgeli)),
        ("kesin medyan (histogram)", len(kova), olcu(kova), medyan_hist),
        ("kesin medyan (sutunu tutarak)", len(sutun), olcu(sutun),
         sorted(sutun)[(len(sutun) - 1) // 2]),
        ("farkli abone sayisi (kesin)", len(aboneler), olcu(aboneler), len(aboneler))]:
    print(y3([ad, durum, bayt_d, 1, sonuc]))
parca_bayt = max(bayt(p) for p in parcalar(YOL, 100))
print(f"parca 100 iken parca {parca_bayt} bayt tutar, abone durumu {olcu(aboneler)} "
      f"bayt; gercek tepe {parca_bayt + olcu(aboneler)} bayttir ve durum payi parca "
      f"boyutu degisince kuculmez")
```

```
islem                            durum ogesi  durum bayt   gecis       sonuc
toplam, sayi, en buyuk                     3          72       1     66667.9
agirlikli ortalama                         2          48       1     20.8402
bolge basina toplam                        5         413       1           5
kesin medyan (histogram)                 321       18292       1        20.7
kesin medyan (sutunu tutarak)           3199      102816       1        20.7
farkli abone sayisi (kesin)             1329       87166       1        1329
parca 100 iken parca 36132 bayt tutar, abone durumu 87166 bayt; gercek tepe 123298 bayttir ve durum payi parca boyutu degisince kuculmez
```

Tablo işlemleri üç kümeye ayırıyor. **Sabit durumlu** olanlar en kolayıdır: toplam, sayım ve en
büyük üç birikeçle biter, ağırlıklı ortalama ikiyle. Bunlar için parçalama bedelsizdir. **Sınırlı
durumlu** olanlar bir sonrakidir: bölge başına toplam beş öğe taşır, kesin medyan 321 öğe. Medyanın
parça parça hesaplanabilmesi genel bir doğru değil, bu kümeye özgü bir varsayımın sonucudur —
okumalar bir ondalıklı ve 5,0 ile 37,0 arasında olduğu için değer uzayı 321 kovaya sığar ve
histogram sütunu tutmadan aynı sayıyı verir: 20,7 m³. Değerler sürekli olsaydı bu satır tablodan
düşerdi.

Üçüncü küme parçalamanın kazancını yiyendir. **Kesin farklı abone sayımı** 1.329 öğelik bir durum
taşır ve o durum 87.166 bayttır. Parça 100 satıra indirildiğinde parçanın kendisi 36.132 bayt
tutar, ama gerçek tepe 123.298 bayttır ve durum payı parça küçüldükçe küçülmez. Parçalamanın
kazancı burada tersine döner: tepenin dörtte üçü artık işlemin kendisindedir. Aynı şey sütunu
bütünüyle tutan medyan hesabı için de geçerlidir — 102.816 bayt, kümenin tamamını tutmaktan farksız.

## Parçalamanın Yaptığı Sıra Varsayımı

```python
# sira.py — ayni kume abone sirasina gore ikinci bir dosyaya yazilir ve ayni
# hesap iki duzende tekrarlanir. Parca parca isleme sessizce bir sira varsayimi
# yapar; varsayim bozuldugunda hata cikmaz, sonuc bosalir.
YOL2 = os.path.join(KLASOR, "okuma_abone.csv")
with open(YOL2, "w", newline="") as f:
    y = csv.writer(f, lineterminator="\n")
    y.writerow(BASLIK)
    y.writerows(sorted(k0, key=lambda x: (x[0], x[2])))


def akan_artis(yol: str, n: int) -> dict:      # durum: yalniz acik olan abone
    artislar, aktif, onceki = {}, None, 0.0
    for p in parcalar(yol, n):
        for s in p:
            a, o = s[0], float(s[4])
            if a != aktif:
                aktif, onceki = a, o
            else:
                artislar[a] = max(artislar.get(a, 0.0), o - onceki)
                onceki = o
    return artislar


def tam_artis(yol: str, n: int) -> tuple[dict, int]:   # durum: butun aboneler
    son, artislar = {}, {}
    for p in parcalar(yol, n):
        for s in p:
            a, o = s[0], float(s[4])
            if a in son:
                artislar[a] = max(artislar.get(a, 0.0), o - son[a])
            son[a] = o
    return artislar, len(son)


G3 = (18, 12, 14, 14, 16)
y4 = lambda h: "".join(str(v).rjust(G3[j]) if j else str(v).ljust(G3[0])
                       for j, v in enumerate(h))
print(y4(["dosya duzeni", "akan durum", "akan sonuc", "tam durum", "tam sonuc"]))
for ad, yol in [("donem sirali", YOL), ("abone sirali", YOL2)]:
    a1 = akan_artis(yol, N)
    a2, durum = tam_artis(yol, N)
    print(y4([ad, 1, len(a1), durum, len(a2)]))
d1, d2 = akan_artis(YOL2, N), tam_artis(YOL, N)[0]
print(f"iki duzenin ayni hesabi ayni sayiyi verir mi: "
      f"{'evet' if d1 == d2 else 'hayir'}; en buyuk artis "
      f"{max(d2.values()):.1f} m3")

# Parca sinirini dogal bir anahtara tasimak: bolge basina bir parca.
bp = {}
for x in k0:
    bp.setdefault(x[3], []).append(x[4])
ort_ort = sum(sum(v) / len(v) for v in bp.values()) / len(bp)
agirlikli = sum(x[4] for x in k0) / len(k0)
fark = abs(ort_ort - agirlikli)
print(f"parca boyutlari {sorted(len(v) for v in bp.values())}; parca ortalamalarinin "
      f"ortalamasi {ort_ort:.4f} m3, agirlikli ortalama {agirlikli:.4f} m3")
print(f"fark {fark:.4f} m3, esigin {fark / ESIK:.1f} kati: esit agirlik varsayimi "
      f"parca boyutlari esit olmadigi anda bozulur")
```

```
dosya duzeni        akan durum    akan sonuc     tam durum       tam sonuc
donem sirali                 1             0          1329            1035
abone sirali                 1          1035          1329            1035
iki duzenin ayni hesabi ayni sayiyi verir mi: evet; en buyuk artis 30.7 m3
parca boyutlari [319, 319, 321, 639, 1601]; parca ortalamalarinin ortalamasi 20.7363 m3, agirlikli ortalama 20.8402 m3
fark 0.1039 m3, esigin 2.1 kati: esit agirlik varsayimi parca boyutlari esit olmadigi anda bozulur
```

Tablonun ilk satırı dersin gizlenen kararıdır. Akan hesap tek bir abonelik durum taşır ve bu
yüzden en ucuz seçenektir; abone sıralı dosyada 1.035 abone için artış üretir ve sonuç, bütün
aboneleri bellekte tutan hesabın sonucuyla birebir aynıdır. Aynı kod dönem sıralı dosyada **hiçbir
hata vermeden 0 abone** için sonuç verir. Boş sonuç bir arıza gibi görünmez: dosya okundu, satırlar
işlendi, çıkış kodu sıfır. Durum tutumluluğu bir sıralama varsayımına dönüşmüştür ve varsayım
dosyanın içinde yazmaz.

İkinci gizlenen karar parçanın nereden kesildiğidir. Parça sınırı satır sayısı yerine doğal bir
anahtara taşındığında — bölge başına bir parça — parçalar 319 ile 1.601 arasında değişir. Parça
ortalamalarının ortalaması 20,7363 m³, ağırlıklı ortalama 20,8402 m³ verir; fark 0,1039 m³ ve
eşiğin 2,1 katıdır, yani yuvarlamadan gelmiş sayılamaz. Fark küçük görünür ama yönü sabittir:
eşit ağırlık varsayımı küçük parçaları büyütür ve parça boyutları birbirinden uzaklaştıkça sapma
büyür. **Parça başına hesaplanan bir ortalamanın nasıl birleştirildiği yazılmıyorsa o ortalama
ölçülmemiş sayılır.**

## Özet

- Parça boyutu 3.199'dan 100'e indiğinde bellek tepesi 1.152.229 bayttan 36.132 bayta, otuz ikide
  bire düşer; geçiş sayısı birdir ve toplam dört parça boyutunda da 66.667,9 m³ çıkar.
- Bir işlemin parça parça hesaplanabilirliğini parça boyutu değil taşınan durum belirler: toplam ve
  ortalama 2–3 öğe, bölge kırılımı 5 öğe, kesin medyan 321 öğe, kesin farklı abone sayımı 1.329 öğe
  taşır.
- Kesin medyanın 321 kovaya sığması genel bir doğru değil, okumaların bir ondalıklı ve 5,0–37,0
  aralığında olmasından gelen bir varsayımdır.
- Parça 100 satıra indiğinde parçanın kendisi 36.132 bayt tutar ama abone durumu 87.166 bayttır;
  gerçek tepe 123.298 bayta çıkar ve durum payı parça küçüldükçe küçülmez.
- Akan hesap abone sıralı dosyada 1.035 abone için doğru sonuç verir, dönem sıralı dosyada hata
  vermeden 0 abone için sonuç verir; parçalama sessizce bir sıra varsayımı yapar.
- Parça sınırı bölgeye taşındığında parça ortalamalarının ortalaması ağırlıklı ortalamadan 0,1039
  m³ ayrışır ve bu fark eşiğin 2,1 katıdır.

## Sonraki Adım

Bu ders belleği parça parça okuyarak kurtardı, ama her parçada dosyanın **bütün alanlarını**
çözümledi: bölge kırılımı için okunan 3.199 satırın altı alanı da metinden nesneye dönüştürüldü,
sonra dördü atıldı. Sorunun sorduğu iki sütun için altı sütun okunuyorsa parçalama yalnız tepeyi
düşürür, yapılan işi düşürmez. Sonraki ders kaydın alanlarını bitişik tutan düzenle sütunu bitişik
tutan düzeni aynı sorguda karşılaştırır ve ölçüyü tek bir sayıya bağlar: aynı cevabı üretmek için
kaç değer okundu.
