63 puan yazan GN⁺ 2025-04-01 | 4 yorum | WhatsApp'ta paylaş
  • Postgres’i daha üretken ve güvenli kullanmaya yardımcı olan pratik kalıpları derleyen bir yazı
  • Her kalıp küçük olsa da biriktiğinde büyük fark yaratır

UUID birincil anahtar kullanımı

  • UUID rastgele olduğu için sıralama veya indeks performansı açısından dezavantajlara sahiptir
  • Sayısal ID’lere göre daha fazla alan kaplar
  • Ancak şu avantajları vardır
    • Veritabanına bağlanmadan da UUID üretilebilir
    • Dışarıya güvenle açığa vurulabilir
  • gen_random_uuid() kullanılarak UUID’nin birincil anahtar olarak otomatik üretilmesi sağlanabilir

created_at ve updated_at alanlarını her zaman ekleyin

  • Hata ayıklama sırasında kaydın ne zaman oluşturulduğunu ve değiştirildiğini bilmek çok faydalıdır
  • updated_at, trigger aracılığıyla otomatik güncellenecek şekilde ayarlanabilir
  • Fonksiyon bir kez oluşturulur, trigger ise her tabloya uygulanmalıdır

Yabancı anahtarlarda on update/delete restrict ayarı kullanın

  • Yabancı anahtar kısıtları tanımlanırken on update restrict on delete restrict mutlaka kullanılmalıdır
  • Veri silinirken yanlışlıkla zincirleme silme yaşanmasını önler
  • Depolama alanı ucuzdur ama veriyi geri getirmek çok zordur; bu yüzden temkinli davranmak daha iyidir

Şema kullanımı önerilir

  • Varsayılan şema public olsa da uygulama büyüdükçe ayrı şemalara bölmek daha iyidir
  • Şemalar namespace gibi çalışır ve farklı şemalar arasında da join yapılabilir
  • Tablo sayısı arttıkça şema kullanımı okunabilirlik ve bakım açısından avantaj sağlar

Enum tablo kalıbını kullanın

  • PostgreSQL’in enum tipi veya check constraint’i yerine enum tablo yaklaşımı daha esnektir
  • Enum değerleri ayrı tabloda tutulursa metadata eklemek veya enum değerlerini genişletmek kolaylaşır
  • Kısıtlar, enum tablosundaki değerlere yabancı anahtarla referans verilerek korunur

Tablo adlarını tekil verin

  • Tablo adlarını çoğul yerine tekil vermek tercih edilir
  • Sorgu yazarken tekil adlar daha açıktır; çoğul adlar iyelik ya da anlamsal karışıklık yaratabilir

Join tablolarını mekanik biçimde adlandırın

  • Çoktan çoğa ilişki için kullanılan join tablolarını, iki tablo adını birleştirerek adlandırmak güvenli ve nettir
  • Örnek: person_pet
  • Kombinasyon üzerine benzersiz indeks eklenerek tekrarlar önlenebilir

Silme yerine soft delete kullanın

  • Veriyi gerçekten silmek yerine, silinme zamanını gösteren revoked_at gibi bir timestamp alanı kullanmak daha iyidir
  • Bu sayede yalnızca silinip silinmediği değil, ne zaman silindiği de izlenebilir
  • Boolean değerden daha fazla bilgi sunduğu için timestamp daha faydalıdır

Durumu (status) log tablosuyla ifade edin

  • Durumu tek bir sütunla ifade etmek yerine, durum değişikliği geçmişi ayrı bir tabloda saklanmalıdır
  • Durumun gerçekleştiği zaman valid_at sütununda açıkça belirtilir
  • En güncel durumu hızlı sorgulamak için latest bayrağı ile benzersiz indeks + trigger ayarlanır
  • Bu yaklaşım, asenkron event işleme veya sıralamanın karışabileceği durumlarda avantaj sağlar

Özel satırlar için system_id ekleyin

  • Yalnızca enum tablolarında değil, belirli “sistem satırları” gereken durumlar da vardır
  • Nullable bir system_id metin alanı eklenip benzersiz indeks tanımlanır
  • system_id sayesinde belirli satırlar açık biçimde sorgulanabilir

View’ları asgari düzeyde kullanın

  • View’lar karmaşık sorguları soyutlamak için faydalıdır ama bakımı zordur
    • Bir sütun kaldırıldığında view’ın yeniden oluşturulması gerekir
    • View üstüne view kurmak performans ve okunabilirlik sorunları yaratır
  • Bu yüzden yalnızca gerektiği kadar ve dikkatli kullanılmalıdır

JSON sorgularını aktif biçimde kullanın

  • Postgres yalnızca JSON saklamada değil, JSON döndüren sorgularda da çok güçlüdür
  • İç içe ilişkiler tek sorguda JSON biçiminde döndürülebilir
  • N+1 problemi olmadan gereken tüm veriler tek seferde alınabilir
  • Dezavantajları: tip bilgisinin kaybolması, tüm verinin aynı anda belleğe yüklenmesi gerekmesi
  • Buna rağmen performans ve yapı açısından avantajları daha büyüktür

4 yorum

 
jhj0517 2025-04-01

> Join tablosuna mekanik olarak ad verin

Ad verirken böyle bir kuralın olması başlı başına güzel bence~

 
halfenif 2025-04-01

UUID7'yi düşünürsek zaman sırasına göre sıralama mümkün olmaz mı?

 
winterjung 2025-04-01

PostgreSQL'de UUID'yi birincil anahtar olarak kullanma hakkında yazısına da göz atmak faydalı olabilir.

 
t7vonn 2025-04-01

soft delete sırasında timestamp ekleme yöntemi güzelmiş.
Birincil anahtar olarak UUID kullanılırsa zamana göre sıralama yapılamayacağı için, snowflake ID veya ULID kullanmak da iyi bir seçenek olabilir. Ancak bu durumda her sunucunun bir sequence number tutması gerekiyor.