← Tüm makaleler
PostgreSQL

PostgreSQL'de Bloat (Şişme) ve VACUUM Tuning

Yoğun yazma trafiğinde PostgreSQL tablolarında biriken bloat'ı dead tuple metrikleriyle izlemek ve autovacuum'u tablo bazında tuning etmek için pratik bir rehber.

Yoğun UPDATE/DELETE trafiği alan PostgreSQL tablolarında zamanla bloat (şişme) oluşur: sorgular yavaşlar, indeksler büyür, disk kullanımı artar. Temel sebep, MVCC modelinin ürettiği dead tuple'lardır. Bu yazıda bloat'ın nasıl oluştuğunu, nasıl izlendiğini ve autovacuum'u tablo bazında nasıl tuning edeceğimizi inceliyoruz.

Bloat neden oluşur?

MVCC gereği bir satır güncellendiğinde PostgreSQL eski versiyonu yerinde bırakır ve yeni bir tuple yazar; eski versiyon artık görünür değildir ama fiziksel olarak heap'te durmaya devam eder — buna dead tuple denir. Dead tuple'lar VACUUM tarafından temizlenip alan tekrar kullanılabilir hâle gelene kadar hem tabloda hem indekslerde yer kaplar. Temizleme hızı yazma hızına yetişemediğinde tablo bloat'a uğrar.

Bloat'ı izlemek

Tuning'e başlamadan önce ölçmek gerekir. pg_stat_user_tables üzerinden dead tuple oranını ve son autovacuum zamanını görebiliriz:

bloat_check.sql
SELECT
  schemaname,
  relname                AS table_name,
  n_live_tup             AS live_tup,
  n_dead_tup             AS dead_tup,
  ROUND(n_dead_tup * 100.0 / NULLIF(n_live_tup + n_dead_tup, 0), 1) AS dead_ratio,
  last_autovacuum
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;

dead_ratio değeri %20'yi geçen ve sık güncellenen (hot) tablolar, autovacuum tuning için önceliklidir.

Autovacuum'u tablo bazında tuning etmek

Global ayarlar her tabloya aynı eşiği uygular; oysa hot tablolar daha agresif bir vacuum ister. scale_factor ve threshold değerlerini tablo bazında düşürerek autovacuum'u daha sık tetikleyebiliriz:

autovacuum_tuning.sql
ALTER TABLE orders SET (
  autovacuum_vacuum_scale_factor  = 0.02,   -- varsayilan 0.2
  autovacuum_vacuum_threshold     = 1000,
  autovacuum_analyze_scale_factor = 0.01,
  autovacuum_vacuum_cost_limit    = 2000    -- daha hizli temizlik
);

scale_factor'ı 0.2'den 0.02'ye çekmek, tablonun yalnızca %2'si değiştiğinde autovacuum'u tetikler; büyük tablolarda bloat birikimini belirgin biçimde azaltır.

Manuel VACUUM ve VACUUM FULL

Birikmiş bloat'ı gidermek için manuel müdahale gerekebilir. Standart VACUUM tabloyu kilitlemeden dead tuple'ların kapladığı alanı tablo içinde tekrar kullanılabilir yapar; ancak bu alanı işletim sistemine iade etmez. Alanı geri vermek için VACUUM FULL gerekir, fakat bu komut tabloya ACCESS EXCLUSIVE lock aldığı için yalnızca bakım penceresinde çalıştırılmalıdır:

SQL
-- Online, kilitsiz rutin temizlik + istatistik tazeleme
VACUUM (VERBOSE, ANALYZE) orders;

-- Alani diske iade eder ama tabloyu kilitler (bakim penceresi!)
VACUUM FULL VERBOSE orders;

Production ortamında VACUUM FULL yerine, tabloyu çevrimdışı bırakmadan çalışan pg_repack uzantısı çoğu senaryoda daha güvenli bir alternatiftir.

Özet

Bloat yönetiminin özü şudur: önce ölçmek, sonra autovacuum'u tabloya göre tuning etmek. Hot tablolarda scale_factor'ı düşürün, dead tuple oranını düzenli izleyin ve VACUUM FULL'ü yalnızca bakım pencerelerinde kullanın. Bu yaklaşım, disk kullanımını ve sorgu sürelerini uzun vadede kontrol altında tutar.