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ın; geçişi sıfır kesinti için aşamalı yapın.
Önce şu sağlamayı yapmakta fayda var: 50M/ay gerçek bir hacim, “verin 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çalayın. Yeni bir partitioned parent (
PARTITION BY RANGE (created_at)) oluşturun ve aylık partition’larıATTACHedin. 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ın. Yeni parent’ı kurun, partition’ları bağlayın, sonra geçmiş veriyi batch’ler hâlinde (örn. 50k’lık dilimlerle, off-peak) partition’lara backfill edin. Bu sırada uygulama yazmaya devam etsin: ya yeni yapıya yönlendiren bir trigger/view kullanın ya da hem eskiye hem yeniye dual-write yapın. Backfill bitince isimleri tek bir transaction içinde takaslayın — kesinti yok.
- İndeksler partition başına oluşur. Parent üstünde tanımladığınız 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şinize yarar, eski ayların indeksi sıcak veriyi yormaz.
- UNIQUE ve FK kuralını unutmayın. 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üzü doğrulayın. - Yaşam döngüsünü
pg_partman’a bırakın. Gelecek ayların partition’larını otomatik oluşturması içinpg_partmankullanın; retention için eski partition’larıDETACH+DROPile silin —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ız 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ştirin; 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.