Performans

PostgreSQL performans optimizasyonu: nereden başlamalı?

Panik hâlinde rastgele indeks eklemek yerine, ölçülebilir bir yöntemle ilerlemek; çoğu sistemde ilk birkaç günde büyük kazanım sağlar.

Bir uygulamanın “yavaş” olması genellikle veritabanının tamamının değil, birkaç sorgunun sorunudur. Bu yazıda, üretim ortamında güvenle uygulayabileceğiniz bir sıralama öneriyoruz: önce ölç, sonra en pahalı işe odaklan, değişikliği doğrula.

1. Ölçüm: en pahalı sorguları bul

pg_stat_statements eklentisi, performans çalışmasının temelidir. Toplam süreye göre ilk 20 sorgu, çoğunlukla iş yükünün büyük kısmını temsil eder.

CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

SELECT
  round(total_exec_time::numeric, 1) AS toplam_ms,
  calls,
  round(mean_exec_time::numeric, 2)  AS ort_ms,
  round((100 * total_exec_time / sum(total_exec_time) OVER ())::numeric, 1) AS pay_yuzde,
  query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 20;

“Ortalama hızlı ama çok sık çağrılıyor” tipi sorgular da en az “tekil olarak yavaş” sorgular kadar önemlidir; pay_yuzde kolonu bunu görünür kılar.

2. Teşhis: EXPLAIN (ANALYZE, BUFFERS) okuma

Şüpheli sorguyu gerçek verilerle çalıştırıp planını inceleyin:

EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT ...;

Bakılacak başlıca işaretler:

  • Seq Scan büyük bir tabloda ve seçici bir WHERE ile birlikteyse, indeks eksik olabilir.
  • Rows Removed by Filter yüksekse, veritabanı gereğinden çok satır okuyup atıyor demektir.
  • tahmini satır ≠ gerçek satır (büyük sapma) genelde eski istatistik ya da bağ (correlation) sorununa işaret eder; ANALYZE tablo; çalıştırın.
  • Nested Loop beklenmedik biçimde büyük dış küme ile çalışıyorsa, join sırası veya indeks sorunu vardır.
  • shared read (BUFFERS) yüksekse, çalışma kümesi bellek dışına taşıyor olabilir.

3. İndeks stratejisi

Sık uygulanan, düşük riskli iyileştirmeler:

  • Bileşik indeks sırası: eşitlik filtreleri önce, aralık filtresi ve sıralama kolonu sonra.
  • Örtük (covering) indeks: INCLUDE (...) ile sık okunan kolonları ekleyip index-only scan'i mümkün kılın.
  • Kısmi indeks: WHERE status = 'active' gibi sorguların büyük kısmı küçük bir alt kümeye bakıyorsa.
  • İfade indeksi: lower(email) gibi fonksiyonla filtreliyorsanız aynı ifadeye indeks verin — ya da filtreyi sargable hâle getirin.

Yeni indeksi üretimde CREATE INDEX CONCURRENTLY ile ekleyin; tabloyu uzun süre kilitlemez. Eklemeden önce yazma maliyetini de düşünün: her indeks, INSERT/UPDATE/DELETE işlemlerini bir miktar yavaşlatır. pg_stat_user_indexes ile hiç kullanılmayan indeksleri tespit edip kaldırmak da bir kazanımdır.

4. Sorgu ve şema düzeltmeleri

  • Sargable filtreler: WHERE date(created_at) = ... yerine created_at >= ... AND created_at < ....
  • Keyset sayfalama: derin OFFSET yerine son görülen anahtardan devam edin.
  • N+1: ORM'in döngü içinde tek tek sorgu atmasını, tek bir JOIN veya IN ile birleştirin.
  • Gereksiz kolon çekmeyin: SELECT *, index-only scan'i ve ağ verimliliğini bozar.

5. Autovacuum ve istatistikler

Yoğun güncellenen tablolarda varsayılan autovacuum eşiği çok yüksek kalır; ölü satırlar (bloat) birikir ve planlayıcı yanılır. Tablo bazında sıkılaştırın:

ALTER TABLE order_lines SET (
  autovacuum_vacuum_scale_factor  = 0.02,
  autovacuum_analyze_scale_factor = 0.01
);

pg_stat_user_tables içindeki n_dead_tup, last_autovacuum ve last_autoanalyze kolonları, ayarın işe yarayıp yaramadığını gösterir.

6. Birkaç yapılandırma parametresi

  • shared_buffers: tipik olarak RAM'in ~%25'i.
  • effective_cache_size: işletim sistemi önbelleği dahil beklenen toplam; planlayıcıyı etkiler.
  • work_mem: sıralama/hash için; oturum ve operasyon başına ayrıldığı için temkinli artırın.
  • random_page_cost: SSD'de 1.1 civarı, indeks kullanımını teşvik eder.

7. Doğrulama ve kalıcılaştırma

Her değişikliğin öncesi/sonrası mean_exec_time ve total_exec_time değerini kaydedin. Kazanımı koruyacak bir uyarı ekleyin: örneğin “bu sorgunun p95 süresi 500 ms'yi aşarsa bildir”. Aksi hâlde birkaç ay sonra aynı sorunla yeniden karşılaşırsınız.

Kısa özet: pg_stat_statements ile en pahalı 20 sorguyu çıkarın → her biri için EXPLAIN (ANALYZE, BUFFERS) → sargable filtre + hedefli indeks + keyset sayfalama → yoğun tablolarda autovacuum sıkılaştırma → öncesi/sonrası kıyas ve uyarı.

Kendi ortamınızda bu adımları birlikte uygulamamızı ister misiniz? Performans optimizasyonu hizmetimize göz atın ya da kısa bir görüşme planlayın.

Yavaş sorgularınızı birlikte hızlandıralım

En pahalı üç sorgunuzu çıkaralım, hızlı kazanımları gösterelim.

Denetim planlayın