PostgreSQL'de bir sorgu yavaşladığında ilk refleks rastgele indeks eklemek olmamalı. Önce veritabanının sorguyu nasıl çalıştırdığını görmeli, ardından ölçüme dayalı bir değişiklik yapmalıyız.
Bu yazı, PostgreSQL EXPLAIN ANALYZE ve doğru indeks tasarımı rehberinin kısa ve uygulanabilir özetidir.
EXPLAIN ile EXPLAIN ANALYZE arasındaki fark
EXPLAIN, PostgreSQL'in seçtiği sorgu planını tahmini maliyetlerle gösterir. EXPLAIN ANALYZE ise sorguyu gerçekten çalıştırır ve her adımın gerçek süresini, dönen satır sayısını ve tekrar sayısını raporlar.
EXPLAIN (ANALYZE, BUFFERS)
SELECT id, customer_id, total_amount
FROM orders
WHERE customer_id = 125
AND created_at >= CURRENT_DATE - INTERVAL '90 days'
ORDER BY created_at DESC;
BUFFERS seçeneği özellikle değerlidir. Sorgunun veriyi bellekten mi yoksa diskten mi okuduğunu görmenizi sağlar. Aynı sorgu test ortamında hızlı, üretimde yavaşsa farkın kaynağı çoğu zaman veri hacmi ve disk erişimidir.
Planda önce hangi alanlara bakılmalı?
Bir sorgu planını incelerken şu dört sinyal çoğu problemi ortaya çıkarır:
- Actual time: Operatörün gerçekten ne kadar sürdüğünü gösterir.
- Rows: Tahmin edilen ve gerçek satır sayıları arasındaki büyük fark istatistik sorununa işaret edebilir.
- Loops: Bir adımın kaç kez tekrarlandığını gösterir. Küçük görünen maliyet binlerce tekrar sonunda pahalı olabilir.
- Buffers: Okunan veya önbellekten kullanılan sayfa miktarını gösterir.
Örneğin plan milyonlarca satır üzerinde Seq Scan gösteriyorsa bu mutlaka hata değildir. Tablo küçükse veya sorgu satırların büyük bölümünü istiyorsa sıralı tarama doğru seçim olabilir. Kararı operatör adına göre değil, gerçek süre ve okunan satır miktarına göre vermek gerekir.
Doğru indeks nasıl seçilir?
İndeks, sorgunun filtreleme ve sıralama biçimine göre tasarlanmalıdır. Yukarıdaki sorgu için aşağıdaki bileşik indeks iyi bir başlangıçtır:
CREATE INDEX CONCURRENTLY idx_orders_customer_created
ON orders (customer_id, created_at DESC);
Burada eşitlik filtresi kullanılan customer_id önce, tarih aralığı ve sıralamada kullanılan created_at sonra gelir. CONCURRENTLY üretim ortamında yazma işlemlerini uzun süre kilitlemeden indeks oluşturmayı sağlar; ancak işlem daha uzun sürer ve transaction bloğu içinde çalıştırılamaz.
Her sorgu için yeni indeks eklemek de doğru değildir. Fazla indeks:
- INSERT ve UPDATE işlemlerini yavaşlatır,
- disk kullanımını artırır,
- bakım ve vacuum maliyetini yükseltir,
- sorgu planlayıcısının seçeneklerini gereksiz yere çoğaltır.
Tahminler neden bozulur?
Plan üzerinde tahmini satır sayısı ile gerçek satır sayısı arasında büyük fark varsa önce istatistikleri yenileyin:
ANALYZE orders;
Dağılımı dengesiz kolonlarda varsayılan istatistik hedefi yetersiz kalabilir. Böyle durumlarda kolon bazında hedef yükseltilebilir; fakat bunu ölçmeden sistem genelinde artırmak gereksiz bakım yükü oluşturur.
Uygulanabilir kontrol listesi
- Problemi gerçek parametrelerle yeniden üretin.
-
EXPLAIN (ANALYZE, BUFFERS)çıktısını alın. - En çok süre harcayan operatörü bulun.
- Tahmini ve gerçek satır sayılarını karşılaştırın.
- Mevcut indeksleri ve indeks kullanımını kontrol edin.
- Tek bir değişiklik yapın ve aynı sorguyu yeniden ölçün.
- İyileştirmenin yazma maliyetine etkisini izleyin.
Performans optimizasyonunun özü budur: tahmin etmek yerine ölçmek, tek değişkeni değiştirmek ve sonucu tekrar ölçmek.
Kurumsal bir API veya yoğun veri kullanan uygulamada sorgu performansı, önbellekleme ve veri modeli birlikte ele alınmalıdır. Bu tür bir sistem için API ve backend geliştirme yaklaşımımı inceleyebilir veya orijinal PostgreSQL rehberinin tamamını okuyabilirsiniz.
Top comments (0)