POSTGRESQL PERFORMANS VE VACUUM

PostgreSQL heap tablo ölü tuple ve vacuum süpürme döngüsü diyagramı

Yüksek yazma trafiği olan bir PostgreSQL sunucusunda iki yol vardır: autovacuum'u varsayılan eşiklerle bırakıp "kendi kendini halleder" demek ya da bakım pencerelerinde manuel VACUUM ve ANALYZE ile devreye girmek. İlk seçenek kolaydır; ikincisi disiplin ister. Üretim ortamında çoğu ekip, sorgu süreleri yavaşlamaya başlayana kadar bu iki yol arasındaki gerçek farkı görmez — ve fark genellikle tablo şişmesi (bloat) olarak kendini gösterir.

Autovacuum Varsayılanları Neyi Vaat Eder, Neyi Etmez

PostgreSQL'in autovacuum_vacuum_scale_factor değeri varsayılan olarak 0.2'dir; yani bir tablonun %20'si "ölü tuple" oranına ulaşana kadar autovacuum tetiklenmez. 10 milyon satırlık bir tabloda bu, 2 milyon ölü satır demektir. Eşik düşük tablolar için makul, büyük tablolar için ise çoğu zaman çok geç.

autovacuum_naptime 1 dakika, autovacuum_max_workers 3'tür. Aynı anda 50 tablonun bakıma ihtiyacı varsa, sıraya girer ve bazıları saatler boyunca beklemek zorunda kalır. Üretimde yaygın gözlenen tablo:

  • n_dead_tup > n_live_tup oranıyla şişmiş tablolar
  • Index-only scan için visibility map'in eski kalması
  • pg_stat_user_tables.last_autoanalyze değerinin günler öncesini göstermesi
  • Sorgu planlayıcısının yanlış istatistiklerle sequential scan seçmesi

Manuel VACUUM/ANALYZE'ın Devreye Girdiği Senaryolar

Bazı yük profilleri autovacuum'un tasarımıyla örtüşmez. Toplu UPDATE veya DELETE sonrası bir kerede milyonlarca satır ölür; varsayılan eşik bu satırları görmezden gelir çünkü işlem öncesi tablo zaten büyüktür. Burada manuel müdahale şarttır:

  1. Toplu silme/güncelleme sonrası VACUUM (VERBOSE, ANALYZE) tablo_adi;
  2. Veri yükleme sonrası ANALYZE ile istatistik tazeleme
  3. Index şişmesi için REINDEX CONCURRENTLY
  4. Saatlik raporlama tablolarında zamanlanmış bakım pencereleri
Dead tuple oranı izleme ve autovacuum tetikleme eşiklerini gösteren grafiği

Tablo Bazlı Override: Ortak Cevap Burada

Cevap genellikle "autovacuum mu manuel mi" değil, "hangi tablo için ne ayar" sorusudur. PostgreSQL bunu tablo başına override etmenize izin verir:

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

Bu, sık güncellenen büyük tablolar için autovacuum'u global ayarları değiştirmeden agresifleştirir. Append-only log tabloları için ise autovacuum_vacuum_insert_scale_factor ile ekleme bazlı bakım tanımlanabilir. Parametrelerin tam listesi ve davranış detayları için resmi rutin vacuum dokümantasyonu başvuru noktası olarak kullanılabilir. PostgreSQL'in iç işleyişine ve performans ayarlarına derinlemesine hakim olmak için PostgreSQL eğitimi içeriğinden yararlanabilirsiniz.

Üretim Ortamı Ölçümleri: Gerçek Sonuçlar

Bir OLTP sisteminde 30 milyon satırlık islemler tablosunda gözlenen tipik tablo:

  • Varsayılan autovacuum: Tablo boyutu 18 GB → 41 GB (bloat ~%55), index scan sürelerinde 3-4x yavaşlama
  • Override edilmiş autovacuum (scale_factor 0.02): Tablo boyutu 21 GB civarında stabilize, bloat %12 altında
  • Sadece haftalık manuel VACUUM: Pencere arasında bloat birikiyor, sorgu süreleri dalgalı seyir izliyor

Sonuç net: tablo başına agresifleştirilmiş autovacuum, çoğu üretim yükünde haftalık manuel VACUUM'dan daha tutarlı performans verir. Manuel VACUUM, autovacuum'un yerine değil tamamlayıcısı olarak konumlanmalıdır — özellikle toplu işlemler sonrası ve VACUUM FREEZE ile transaction ID wraparound önlemleri için.

İzleme: Ne Ölçmediğinizi Bilemezsiniz

VACUUM stratejisi izleme olmadan tahmindir. pg_stat_user_tables, pg_stat_progress_vacuum ve pg_stat_activity birlikte okunmalıdır. İzlenmesi gereken minimum metrik seti:

  • n_dead_tup / n_live_tup oranı (tablo bazında, %20 üstü alarm)
  • last_autovacuum ve last_autoanalyze zaman damgaları
  • autovacuum_count trendinin günlük değişimi
  • age(relfrozenxid) — wraparound için kritik
  • Bloat tahmini için pgstattuple uzantısı veya check_postgres çıktısı
VACUUM FREEZE ve relfrozenxid yaşlanmasıyla transaction ID wraparound koruması

Bakım Penceresi mi, Sürekli Bakım mı?

Eski Oracle alışkanlığıyla gelen ekipler "haftalık bakım penceresi" düşünür. PostgreSQL felsefesi tersinedir: bakım sürekli ve küçük adımlarla yapılmalıdır. autovacuum_vacuum_cost_limit ve autovacuum_vacuum_cost_delay parametreleri tam bunun içindir — I/O bütçesini sınırlayarak bakımı görünmez kılmak. PostgreSQL 12 sonrası cost_delay varsayılanı 2 ms'ye düşürüldü; eski sürümlerden gelen 20 ms ayarıyla çalışan sistemlerde autovacuum'un neden "yetişemediği" çoğu zaman bu tek satırda gizlidir. PostgreSQL ile performans yönetimi pratiklerini farklı senaryolarda görmek için PostgreSQL eğitimi sayfasını inceleyebilirsiniz.

Pratik özet: varsayılan autovacuum çoğu üretim yükü için yetersizdir, ama tamamen manuel bakım da sürdürülebilir değildir. Doğru cevap; tablo başına agresif autovacuum override'ları + toplu işlem sonrası nokta atışı manuel VACUUM ANALYZE + bloat ve wraparound metriklerinin sürekli izlenmesidir. Bu üçü birlikte çalıştığında, bakım artık bir "pencere" değil, sistemin sessiz bir alt katmanı haline gelir.