SanalOrtam.net
Yapay Zekâ ve Yazılım

PostgreSQL'de tablo bölümlendirme (partitioning): büyüyen tabloları evcilleştirmek

Yüz milyonlarca satırlık satış ya da log tablosu yavaşladı mı? Tarihe göre bölümlendirme ile sorguları hızlandırmanın ve eski veriyi saniyeler içinde arşivlemenin yolu.

PostgreSQL'de tablo bölümlendirme (partitioning): büyüyen tabloları evcilleştirmek

Eğitimlerde partitioning laboratuvarı en uzun süren bölümdü: kalıtım (inheritance) ile alt tablolar açar, CHECK kısıtları yazar, gelen kaydı doğru alt tabloya yönlendirmek için trigger fonksiyonları kodlardık. PostgreSQL 10 ile gelen bildirimsel (declarative) bölümlendirme bu işin neredeyse tamamını ortadan kaldırdı.

Ne zaman gerekir?

  • Tablo çok büyüdüyse (onlarca GB, yüz milyonlarca satır) ve sorguların çoğu belirli bir aralığa (son ay, son yıl) bakıyorsa.
  • Eski veriyi düzenli olarak silmeniz ya da arşivlemeniz gerekiyorsa. Milyonlarca satırı DELETE ile silmek yerine bir bölümü tek komutla ayırmak çok daha hızlıdır.

Küçük tablolarda bölümlendirme fayda yerine karmaşıklık getirir; önce doğru indeksleri deneyin.

Tarihe göre bölümlendirme örneği

CREATE TABLE satislar (
    id           bigint        NOT NULL,
    satis_tarihi date          NOT NULL,
    magaza_id    int           NOT NULL,
    tutar        numeric(12,2) NOT NULL,
    PRIMARY KEY (id, satis_tarihi)
) PARTITION BY RANGE (satis_tarihi);

CREATE TABLE satislar_2026_09 PARTITION OF satislar
    FOR VALUES FROM ('2026-09-01') TO ('2026-10-01');
CREATE TABLE satislar_2026_10 PARTITION OF satislar
    FOR VALUES FROM ('2026-10-01') TO ('2026-11-01');

-- Hiçbir aralığa uymayan kayıtlar için güvenlik ağı
CREATE TABLE satislar_diger PARTITION OF satislar DEFAULT;

-- Ana tabloda açılan indeks tüm bölümlere otomatik uygulanır
CREATE INDEX ON satislar (magaza_id);

Dikkat: Bölümlenmiş tabloda birincil anahtar ve benzersiz kısıtlar bölümleme sütununu içermek zorundadır; bu yüzden anahtar (id, satis_tarihi) oldu.

Artık INSERT INTO satislar ... dediğinizde kayıt doğru bölüme kendiliğinden gider; trigger yazmanıza gerek yok.

Bölüm budama (partition pruning)

EXPLAIN SELECT sum(tutar) FROM satislar
WHERE satis_tarihi >= '2026-10-01' AND satis_tarihi < '2026-11-01';

Plan çıktısında yalnızca satislar_2026_10 bölümünün tarandığını görürsünüz. Planlayıcı diğer bölümlere hiç dokunmaz; büyük tablolarda kazancın asıl kaynağı budur.

Eski veriyi arşivlemek

ALTER TABLE satislar DETACH PARTITION satislar_2026_09 CONCURRENTLY;
-- İsterseniz pg_dump ile dışarı alıp silebilirsiniz:
DROP TABLE satislar_2026_09;

CONCURRENTLY (PostgreSQL 14+) ayırma işlemini tabloyu uzun süre kilitlemeden yapar.

Diğer bölümlendirme türleri

  • LIST: Bölge, ülke, şirket kodu gibi sabit değerlere göre (PARTITION BY LIST (bolge)).
  • HASH: Doğal bir aralık yoksa, yükü eşit dağıtmak için (PARTITION BY HASH (musteri_id)).

Pratik ipuçları

  • Gelecek ayların bölümlerini önceden açın; bunu bir zamanlanmış görevle ya da pg_partman eklentisiyle otomatikleştirin.
  • Bölüm sayısını makul tutun. Binlerce küçük bölüm, planlama süresini uzatır.
  • Sorgularınızda bölümleme sütununu (satis_tarihi) koşul olarak kullanmayı alışkanlık hâline getirin; budama ancak böyle çalışır.

Kaynak: PostgreSQL belgeleri, Table Partitioning

TH // yazarTaner HacıoğluYazılım ERP Müdürü

Yorumlar (0)

Yorum yazın

Gönderiler onaylandıktan sonra yayımlanır.

// aynı bölümden

Bunlar da ilginizi çekebilir