İçeriğe geç
Muhammet Şafak
en
Soran: Furkan Cevaplandı:

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ı.

  1. Native declarative RANGE ile parçalayın. Yeni bir partitioned parent (PARTITION BY RANGE (created_at)) oluşturun ve aylık partition’ları ATTACH edin. Eski monolitik tablonun aksine, sorgu sadece ilgili aya değer; partition pruning sayesinde basit select’ler tekrar hızlanır.
  2. 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.
  3. İ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.
  4. 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.
  5. Yaşam döngüsünü pg_partman’a bırakın. Gelecek ayların partition’larını otomatik oluşturması için pg_partman kullanın; retention için eski partition’ları DETACH + DROP ile silin — DELETE taraması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

Paylaş:

Yorumlar

Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.

Diğer Sorular

Tüm sorular

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi