Modül 8 · Toplu İşleme (Batch) · ⏱ 7 dk

Spark nedir? Pizzacı ekibi analojisi

What is Spark

Bu derste neler öğreneceksin

  • Spark ın dağıtık yapısını açıklar
  • RDD vs DataFrame farkını bilir
  • PySpark + DuckDB karşılaştırması yapar

Spark: Büyük Verinin Dağıtık Hesaplama Motoru

Veri mühendisliğinde “büyük veri” genellikle tek bir makineye sığmayan veri demektir. Petabyte ölçeğinde günlük event log’ları, yıllık GPS izleri, IoT sensör verisi — bunları tek bir sunucuyla işlemek fiziksel olarak mümkün değil. Apache Spark, bu sorunu “veriyi böl, birçok makinede paralel işle, sonuçları birleştir” yaklaşımıyla çözen açık kaynak bir motor.

2014’te çıkan ilk sürümden bu yana sektör standardı haline geldi: Databricks, Amazon EMR, Google Dataproc, Azure Synapse — hepsi Spark etrafında dönüyor.

Mimari: Driver, Executor, Cluster

Spark’ın üç temel bileşeni var:

  • Driver (master): İşi planlayan beyin. SparkSession, kullanıcının yazdığı kodu DAG (Directed Acyclic Graph — yönlü döngüsel olmayan grafik) halinde bir iş planına çevirir.
  • Executor (worker): Asıl hesaplamayı yapan kol. Her executor JVM üzerinde çalışan bir süreçtir; belirli sayıda task (görev) paralel yürütür.
  • Cluster Manager: Dış kaynak yöneticisi (YARN, Mesos, Kubernetes, Spark Standalone). Driver’a “şu kadar executor açabilirsin” der.
graph LR
    A[Driver] -->|planla| B[Cluster Manager]
    B -->|tahsis et| C[Executor 1]
    B -->|tahsis et| D[Executor 2]
    B -->|tahsis et| E[Executor N]
    C --> F[(Partition 1)]
    D --> G[(Partition 2)]
    E --> H[(Partition N)]

Bir veri okunduğunda Spark onu partition’lara (parçalara) böler. Her executor kendi partition’ı üzerinde çalışır. Sonuçlar shuffle aşamasında birleştirilir — shuffle maliyetli olduğu için iyi bir Spark programcısı shuffle’ı en aza indirmeye çalışır.

RDD: Spark’ın Kökeni (Eski Usul)

İlk Spark sürümlerinde tek veri yapısı vardı: RDD (Resilient Distributed Dataset). Üç kelimenin açılımı:

  • Resilient: Hata olursa lineage (soy kütüğü) üzerinden yeniden hesaplanabilir.
  • Distributed: Veri birçok makineye dağıtılır.
  • Dataset: Satırlık veri koleksiyonu.

RDD düşük seviyeli bir API’dir. Her şeyi lambda fonksiyonları ile yaparsın:

# RDD ile: alt seviye, fonksiyonel
rdd = sc.parallelize([
    ("margherita", 50), ("sucuklu", 70), ("mozzarella", 60),
    ("pepperoni", 75), ("veggie", 55), ("kasar", 65),
])

# Map: fiyatı 1.18 ile çarp (KDV)
kdvli = rdd.map(lambda kv: (kv[0], kv[1] * 1.18))

# Filter: pahalı pizzalar
pahali = kdvli.filter(lambda kv: kv[1] > 70)

# Reduce: ortalama fiyat
toplam = pahali.map(lambda kv: kv[1]).reduce(lambda a, b: a + b)
adet = pahali.count()
print(f"Ortalama: {toplam / adet:.2f} TL")

RDD’nin avantajı esneklik: istediğin her şeyi lambda ile yazabilirsin. Dezavantajı: Spark senin kodu optimize edemez. Çünkü Spark “bu kullanıcı ne yapıyor” diye bakamıyor — sadece sen söylediğin adımları yürütüyor.

2026’da RDD ne zaman kullanılır? Neredeyse hiç. Eski kod okurken veya çok düşük seviyeli bir kontrol gerektiğinde (ör. özel bir partitioner) karşına çıkar. Yeni proje yazıyorsan DataFrame API kullan.

DataFrame: Yüksek Seviye, Optimize Edilebilir

DataFrame API’si RDD’nin üzerine kurulu bir soyutlama. Sen tablo görürsün, Spark bir SQL/planner motoru (Catalyst) görür.

# DataFrame ile: yüksek seviye, optimize
df = spark.createDataFrame(
    [("margherita", 50), ("sucuklu", 70), ("mozzarella", 60),
     ("pepperoni", 75), ("veggie", 55), ("kasar", 65)],
    ["pizza", "fiyat"],
)

from pyspark.sql.functions import col, avg
df.filter(col("fiyat") > 70).agg(avg("fiyat")).show()

Aynı sonuç — ama Spark bunu arka planda optimize eder: predicate pushdown (filtreyi erkene al), projection pruning (gereksiz sütunu atla), join reordering gibi planlamaları Catalyst otomatik yapar. RDD’de bunları sen elle yapmak zorunda kalırdın.

DataFrame API’si iki stilde yazılabilir:

# 1) Zincirleme (Pythonic)
df.filter(col("fiyat") > 70).select("pizza").show()

# 2) SQL ifadesi
df.createOrReplaceTempView("pizzalar")
spark.sql("SELECT pizza FROM pizzalar WHERE fiyat > 70").show()

İkisi de aynı plana derlenir.

PySpark vs DuckDB: Aynı Tablo, Farklı Motor

Spark dışında bir de DuckDB var. DuckDB, tek bir makinede çalışan, gömülü (in-process) bir analitik veritabanı motoru. Yani ayrı bir sunucu kurmuyorsun, Python içinden import duckdb ile çalışıyor.

KriterPySparkDuckDB
ÖlçekTek makineden petabyte’aTek makine (genelde 10-200 GB arası rahat)
Kurulumpip install pyspark (JVM indirir, 300 MB+)pip install duckdb (50 MB)
ClusterBirçok makineye dağılırTek makinede paralelleştirir (çok çekirdek)
API yüzeyiGeniş (Spark SQL, MLlib, Structured Streaming)Sadece SQL + DataFrame
Ne zaman seçilirVeri makineye sığmıyor, üretim pipelineTek laptop, orta veri, hızlı analiz
Yerel geliştirmeAğır (JVM başlatır)Çok hafif

Production kararı: Bu kursta varsayılan Polars (DuckDB benzeri, tek makine). Veri 100 GB’ı geçiyorsa Spark’a terfi et. Pratikte startup’ların çoğu verisi 50 GB altında — Spark’a hiç geçmeden ömür boyu Polars/DuckDB yeter.

PySpark ile Hızlı Demo

JVM’i yerel olarak ayağa kaldırıp 10 milyon satırlık veri üzerinde groupBy:

from pyspark.sql import SparkSession
import random

spark = SparkSession.builder \
    .appName("mini-demo") \
    .master("local[4]") \
    .getOrCreate()

# 10M satır üret
random.seed(42)
data = [
    (f"user_{i}", random.choice(["A", "B", "C"]), random.randint(1, 1000))
    for i in range(10_000_000)
]
df = spark.createDataFrame(data, ["user", "segment", "amount"])

# Plan: segment başına toplam ve ortalama
df.groupBy("segment").agg(
    {"amount": "sum", "amount": "avg"}
).show()

local[4] demek “yerel JVM’de 4 çekirdek kullan” demek. Production’da cluster modu açarsın.

Özet

Bugün öğrendik:

  • Spark, dağıtık hesaplama motoru: driver planlar, executor’lar çalıştırır.
  • Partition’lar verinin dağıtık parçaları; shuffle parçalar arası veri taşıma (maliyetli).
  • RDD eski API, DataFrame yeni API; yeni kodda DataFrame.
  • PySpark Python’dan Spark; DuckDB tek makinede analitik motor.
  • Küçük veri için Polars/DuckDB, büyük veri için Spark; çoğu startup verisi Polars ile yaşar.

Alıştırma

  1. pip install pyspark kur, yukarıdaki demo’yu çalıştır. Spark UI’a localhost:4040 üzerinden bak (DAG ve stage’leri göreceksin).
  2. df.groupBy("segment").count() ile sayım yap. Plan neden 2 stage gösteriyor?
  3. Bir cümle yaz: “Kendi projemde PySpark mı DuckDB mi seçerdim, hangi koşulda?”

Sıradaki

Spark’ın temellerini gördün. Şimdi gerçek bir DataFrame batch iş yazıyoruz →