Partition & Cluster: büyük defteri yıllara böl
Partition and Cluster
Bu derste neler öğreneceksin
- Partitioning tarih aralık kavrar
- Clustering yüksek kardinalite açıklar
- Performans farkını ölçer
Dev Defter Bölme Sanatı
Düşün: elinde 10 yıllık bir okul defteri var. Her sayfada o günkü öğrenciler, notlar, etkinlikler yazıyor. Bir gün annen diyor ki “2024 yılında kaç kere yoklama alındı?” Sen defteri açıp baştan sona tarıyorsun. Saatler sürüyor.
Şimdi aynı defterin her yıl için ayrı bir cilt olduğunu düşün: 2016 cildi, 2017 cildi, 2018 cildi… Annen “2024” deyince sen sadece 2024 cildini raftan alıyorsun, 5 saniyede buluyorsun. İşte bu partitioning (bölümleme).
Bir başka örnek: aynı ciltlerin içinde öğrencileri alfabetik sıraya koymuş ol. “Ayşe” notunu bulmak için tüm cildi taramana gerek yok, “A” bölümüne atlıyorsun, sonra “y” sırasına. Bu da clustering.
Partitioning (Bölümleme): Tarihe Göre Rafları Ayır
BigQuery’de partitioning, tabloyu tarih veya aralık bazında fiziksel olarak ayrı parçalara böler. Sorgun “2024” diyorsa, sadece 2024 parçası okunur. Gerisine hiç bakılmaz.
En yaygın türü DATE/TIMESTAMP partitioning: tabloyu günlük, aylık ya da yıllık dilimlere böler. Örneğin taksi yolculukları tablosu pickup_date (yolculuk tarihi) sütununa göre günlük partitionlanmışsa, 2024 Ocak’taki yolculukları sormak sadece 31 partition’ı okur (365’in 1/12’si).
-- Partition'lı tablo oluştur
CREATE TABLE my_dataset.taxi_2024
PARTITION BY DATE(pickup_datetime)
AS
SELECT * FROM `bigquery-public-data.new_york_taxi.taxi_trips`
WHERE pickup_datetime BETWEEN '2024-01-01' AND '2024-12-31';
Bir sorgu çalıştırdığında BigQuery üstte “This query will process XXX MB” yazar. Partition kullanırsan bu sayı 10-100 kat düşer. Çünkü tüm tablo yerine sadece ilgili günleri okur.
Clustering (Kümeleme): Sıralı Raflar
Partition’ı büyük filtreler için düşün (tarih, ay, bölge). Ama ya sütun çok fazla farklı değer içeriyorsa? Mesela passenger_count (1-6 arası 6 değer) için partition işe yaramaz — bölünecek anlamlı bir sınır yok. Ama vendor_id ya da rate_code (yüzlerce farklı değer) gibi yüksek kardinaliteli sütunlar için clustering kullanılır.
Clustering, BigQuery’ye “bu sütunun değerlerine göre verileri sıralı tut” der. Sorgu “vendor_id = 1” isterse, sadece o kümeye bakar. Parquet dosyaları içinde sıralı yerleşim sağlandığı için okuma çok hızlı olur.
-- Partition + Cluster birlikte (en güçlü kombinasyon)
CREATE TABLE my_dataset.taxi_partitioned_clustered
PARTITION BY DATE(pickup_datetime)
CLUSTER BY vendor_id, passenger_count
AS
SELECT * FROM `bigquery-public-data.new_york_taxi.taxi_trips`;
Ne Zaman Hangisi?
| Durum | Çözüm |
|---|---|
| Tarih bazlı sorgu (son ay, geçen yıl) | Partition by DATE |
| Çok farklı değer (şehir, ürün kodu, kullanıcı id) | Cluster |
| Hem tarih hem de sık sorgulanan sütun | İkisi birlikte |
Altın kural: Partition sütununu her zaman WHERE içinde kullan (tarih aralığı). Cluster sütunlarını da sık filtrelediğin sütunlardan seç.
Performans Farkını Kendin Gör
BigQuery konsolunda bigquery-public-data.new_york_taxi.taxi_trips tablosuna iki sorgu at:
Partition kullanmadan (tüm 1 milyar+ satır):
SELECT COUNT(*) FROM `bigquery-public-data.new_york_taxi.taxi_trips`
WHERE pickup_datetime BETWEEN '2024-01-01' AND '2024-12-31';
-- ~9 GB tarar
Aynı tablonun partitioned versiyonunda:
SELECT COUNT(*) FROM my_dataset.taxi_partitioned_clustered
WHERE DATE(pickup_datetime) = '2024-01-15';
-- ~150 MB tarar (60 kat küçük!)
Tarih filtresini DATE(pickup_datetime) = '...' şeklinde yazdığında BigQuery partition pruning yapar — sadece o günün partition’ını okur. Bu, üretimde her gün çalışan pipeline’lar için kritik bir kazanç.
Ne Öğrendik?
- Partition büyük tabloları tarih/aralık bazında böler, büyük filtreler için.
- Cluster yüksek kardinaliteli sütunlar için sıralı saklama yapar.
- İkisini birlikte kullanmak en güçlü kombinasyon.
- Sonuç: aynı sonuç, 10-100 kat daha az veri tarandı, sorgu daha hızlı, fatura daha düşük.