PostgreSQL tablo partitioning'e sıfır kesinti ile nasıl geçerim?
Soru
SaaS uygulamamızda kullanıcı hareket loglarını tuttuğumuz `audit_logs` tablosu aylık 50M satır büyüyor; tablo büyüdükçe basit `select`'ler bile yavaşladı. PostgreSQL'in declarative partitioning'iyle bu tabloyu `created_at`'e göre aylık partition'lara ayırmak istiyorum. Canlı veriyi sıfır kesinti ile bu yeni yapıya nasıl taşırım? İndeksler ve foreign key bağımlılıkları bundan nasıl etkilenir?
Cevap
Kısa cevap: Aylık 50M satır gerçekten büyük — partitioning burada doğru hamle. created_at üzerinden aylık RANGE declarative partitioning kullan; geçişi sıfır kesinti için aşamalı yap.
Önce şu sağlamayı yapmakta fayda var: 50M/ay gerçek bir hacim, “verim gerçekten büyük mü yoksa kötü mü modellenmiş” sorusunun cevabı burada net — gerçekten büyük. Partition mantıklı.
- Native declarative RANGE ile parçala. Yeni bir partitioned parent (
PARTITION BY RANGE (created_at)) oluştur ve aylık partition’larıATTACHet. Eski monolitik tablonun aksine, sorgu sadece ilgili aya değer; partition pruning sayesinde basitselect’ler tekrar hızlanır. - Geçişi sıfır kesinti ile yap. Yeni parent’ı kur, partition’ları bağla, sonra geçmiş veriyi batch’ler hâlinde (örn. 50k’lık dilimlerle, off-peak) partition’lara backfill et. Bu sırada uygulama yazmaya devam etsin: ya yeni yapıya yönlendiren bir trigger/view kullan ya da hem eskiye hem yeniye dual-write yap. Backfill bitince isimleri tek bir transaction içinde takasla — kesinti yok.
- İndeksler partition başına oluşur. Parent üstünde tanımladığın indeksi Postgres her partition’a otomatik yayar (propagate). Yani global tek bir B-tree değil, her ay için ayrı indeks; bu aslında işine yarar, eski ayların indeksi sıcak veriyi yormaz.
- UNIQUE ve FK kuralını unutma. Partitioned tabloda global bir UNIQUE/PK, partition anahtarını içermek zorundadır — yani PK’in
(id, created_at)olur. Tabloya referans veren FK’ler de bundan etkilenir; modern PG’de partitioned tabloya FK kurmak çalışır ama sürümünü doğrula. - Yaşam döngüsünü
pg_partman’a bırak. Gelecek ayların partition’larını otomatik oluşturması içinpg_partmankullan; retention için eski partition’larıDETACH+DROPile sil —DELETEtaramasından çok daha ucuz, anında.
Sonuç: created_at üzerinde declarative RANGE, batch’li backfill, her unique key’de partition anahtarı, yaşam döngüsü için pg_partman. Geçişi dual-write + tek transaction’lık isim takasıyla kurarsan canlı sistem hiç durmaz. Bu tür DB derinliklerine girmeden önce ölçeklenme ihtiyacının gerçekten “büyük veri” mi olduğunu netleştir; bu vakada öyle.
İlgili Yazılar
Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.