• 30.10.2026 19:05:06
  • İbrahim Gökyar

Web geliştiriciler için PostgreSQL rehberi: sorgu optimizasyonu, indeksleme, JSONB, partitioning, bağlantı havuzu ve bakım pratikleriyle üretimde güvenli ve hızlı veri yönetimi.

PostgreSQL Performans, JSONB ve Bağlantı Havuzu: Modern Web Uygulamaları

PostgreSQL, modern web uygulamaları için esnek, güçlü ve geniş özellik seti sunan bir ilişkisel veritabanıdır. Bu makalede, özellikle web geliştiricilerin üretim ortamlarında karşılaştığı performans problemlerini çözmeye yönelik pratik yaklaşımlar, JSONB kullanımı, indeks stratejileri, partitioning, bağlantı havuzu yönetimi ve rutin bakım işlemleri ele alınacaktır. Hedefimiz, uygulamanızın gecikmesini azaltmak, kaynak kullanımını optimize etmek ve ölçeklenebilirliği artırmaktır.

Sorgu Analizi ve EXPLAIN ile Başlamak

Her performans çalışmasının merkezinde düzgün bir sorgu analizi vardır. PostgreSQL'de EXPLAIN ve EXPLAIN ANALYZE komutları sorgunun nasıl çalıştığını, hangi indekslerin kullanıldığını ve gerçek çalışma süresini gösterir. İlk adım olarak problemli bir sorguyu EXPLAIN ANALYZE ile çalıştırın ve planı yorumlamayı öğrenin.

Örnek temel kullanım:

EXPLAIN ANALYZE
SELECT * FROM orders WHERE customer_id = 42;

Planı okurken özellikle seq scan, index scan, nested loop gibi operasyonları ve satır/saniye metriklerini değerlendirin. Eğer beklenmedik bir seq scan görüyorsanız, uygun indeks eksik olabilir veya istatistikler güncel değildir.

İndeksleme Stratejileri: Bütünlük ile Performans Dengesi

İyi seçilmiş indeksler sorgu performansını dramatik şekilde iyileştirir, fakat her indeks yazma maliyetini artırır. Sıklıkla sorgulanan sütunlar, JOIN koşulları ve WHERE filtreleri için indeks oluşturun. Ayrıca, çoklu sütun indeksleri (multi-column) ve kısmi indeksler (partial index) ile gereksiz indeks maliyetinden kaçınabilirsiniz.

Örnek kısmi indeks:

CREATE INDEX idx_orders_active ON orders (created_at)
WHERE status = 'active';

Bazı durumlarda expression indeksler de çok faydalıdır. Örneğin lowercase karşılaştırmaları için:

CREATE INDEX idx_users_email_lower ON users (lower(email));

JSONB: Esnek Veri Modelleri ve Performans İpuçları

JSONB sütunları, yarı-yapısal veriyi saklamada esneklik sağlar ve ilişkisel tablo modelleriyle birlikte kullanılabilir. Ancak JSONB kullanırken indeksleme ve sorgu yazımına dikkat etmek gerekir. JSONB sütunları için GIN indeksleri sıklıkla tercih edilir.

Basit bir JSONB GIN indeksi örneği:

ALTER TABLE events
ADD COLUMN payload jsonb;
CREATE INDEX idx_events_payload_gin ON events USING gin (payload);

Belirli anahtarlar üzerinde sorgu yapıyorsanız expression tabanlı GIN veya BTREE indekslerini düşünün. Ayrıca, sık erişilen alanları ayrı sütunlara taşımak (hybrid model) hem sorgu performansını artırır hem de indeks maliyetini düşürür.

Partitioning ile Veritabanını Yönetin

Büyük tablolar için partitioning (bölümlendirme) sorgu performansını ve bakım işlemlerini iyileştirir. Partitioning genelde tarih temelli (range) veya hash tabanlı olarak uygulanır. Partitioning ile eski verileri parça parça temizlemek, VACUUM ve index rebuild gibi operasyonları daha hızlı yapmak mümkün olur.

Basit tarih tabanlı partitioning örneği (PostgreSQL native partitioning):

CREATE TABLE logs (
  id serial PRIMARY KEY,
  created_at timestamptz NOT NULL,
  message text
) PARTITION BY RANGE (created_at);

CREATE TABLE logs_2026 PARTITION OF logs
FOR VALUES FROM ('2026-01-01') TO ('2027-01-01');

Partition seçimi yaparken sorgu desenlerinizi analiz edin. Eğer çoğu sorgu tarih aralığına göre filtreliyorsa range partitioning uygundur. Hash partitioning ise eşit dağılım gerektiğinde işe yarar.

Bağlantı Havuzu (Connection Pooling) ve Uygulama Katmanı

Web uygulamalarında en sık gözardı edilen performans problemi veritabanı bağlantılarının yönetimidir. Her istek için yeni bağlantı açıp kapamak maliyetli olabilir. PgBouncer gibi bağlantı havuzları, uygulama ile veritabanı arasındaki bağlantı sayısını azaltır ve kaynak kullanımını optimize eder.

Basit PgBouncer kullanım senaryosu: uygulama pool ile yüksek sayıda kısa ömürlü istek gönderirken PgBouncer arka planda sınırlı sayıda gerçek bağlantı yönetir. Bu sayede veritabanı üzerindeki bağlantı yükü kontrol altında tutulur. Ayrıca, uygulama tarafında da ORM bağlantı pool ayarlarını (max connections, idle timeout) gerçek trafik profiline göre ayarlayın.

Bakım, VACUUM ve İstatistiklerin Güncel Tutulması

PostgreSQL'de düzenli bakım otomasyonunu sağlamak performans için kritiktir. Autovacuum, çoğu durumda yeterli olsa da büyük tablolar veya yoğun yazma iş yükleri için parametreleri özelleştirmek gerekebilir. VACUUM ve ANALYZE işlemleri, boş alan yönetimi ve sorgu planlayıcının doğru istatistiklere sahip olması için zorunludur.

Öneriler: büyük toplu güncellemeler öncesi/sonrası VACUUM çalıştırmak, autovacuum eşiğini gözden geçirmek ve pg_stat_user_tables üzerinden dead tuple sayısını takip etmek. Ayrıca, index bloat kontrolü için düzenli olarak REINDEX veya pg_repack kullanımı değerlendirilebilir.

Sık Sorulan Sorular

1. JSONB yerine tamamen ilişkisel model mi kullanmalıyım?

JSONB esneklik sağlar ama sık sorgulanan alanlar için ayrı sütunlar tercih edin. Karma modeller genelde en iyi dengeyi verir: yapısal veriler sütunlarda, değişken yapıdaki veriler JSONB'de saklanır.

2. PgBouncer mı, Pgpool-II mi tercih etmeliyim?

Basit bağlantı havuzu ve yüksek performans için genelde PgBouncer yeterlidir. Pgpool-II daha fazla özellik (replication, load balancing, query caching gibi) sunar ama karmaşıklığı artar. İhtiyacınıza göre karar verin: basit havuzlama için PgBouncer, ekstra özellik gerekiyorsa Pgpool-II.

3. Partitioning her zaman performans arttırır mı?

Hayır. Partitioning, doğru kullanım senaryolarında (büyük tablolar, tarih bazlı sorgular, TTL gereksinimleri) fayda sağlar. Küçük tablolarda veya sorgu desenleri partition'ı kullanmayı gerektirmiyorsa ek karmaşıklık ve yönetim maliyeti yaratır.

İlgili Eğitim

Sonuç

PostgreSQL ile başarılı bir üretim ortamı kurmak, tek bir sihirli ayardan ziyade bir dizi iyi uygulama gerektirir: sorgu analizi, doğru indeksleme, JSONB ve ilişkisel model kararı, partitioning, bağlantı havuzu kullanımı ve düzenli bakım. Bu başlıkları sistematik şekilde ele alırsanız uygulamanızın gecikmesini azaltır, veritabanı yükünü dengeler ve ölçeklenebilirliği artırırsınız. Makaledeki örnekleri kendi veri modelinize göre uyarlayarak başlayın ve EXPLAIN ANALYZE ile her değişikliğin etkisini ölçmeyi unutmayın.