PostgreSQL neden eski satırları hemen silmez?
PostgreSQL MVCC kullandığı için bir satır güncellendiğinde eski versiyon hemen ortadan kalkmaz. Başka bir transaction hâlâ eski versiyonu görmeye ihtiyaç duyabilir. Bu tasarım tutarlılık sağlar ama bedeli şudur: eski satır izlerinin düzenli temizlenmesi gerekir.
Vacuum işte bu temizlik işidir. Çoğu zaman autovacuum bunu arkadan sessizce yapar. Sorun, yazma yoğunluğu arttığında, uzun transactionlar açık kaldığında veya tablo ayarları iş yüküne uymadığında başlar.
- UPDATE ve DELETE dead tuple üretir.
- Uzun transactionlar eski satırların temizlenmesini geciktirebilir.
- Autovacuum her tablo için aynı hızda ve aynı sıklıkta yetmeyebilir.
- Bloat yalnızca disk değil, sorgu performansı problemidir.
Önce hangi tablo şişiyor, onu bulun
Vacuum konuşurken genelleme yapmak kolaydır; ama çözüm tablo bazında bulunur. Hangi tabloda dead tuple birikiyor, en son autovacuum ne zaman çalışmış, analyze istatistikleri güncel mi, önce bunları görmek gerekir.
Dead tuple ve autovacuum görünümü
SELECT relname, n_live_tup, n_dead_tup, last_autovacuum, last_autoanalyze, vacuum_count, autovacuum_count FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 20;
Tablo ve indeks boyutu
SELECT relname, pg_size_pretty(pg_total_relation_size(relid)) AS total_size, pg_size_pretty(pg_relation_size(relid)) AS table_size, pg_size_pretty(pg_indexes_size(relid)) AS indexes_size FROM pg_catalog.pg_statio_user_tables ORDER BY pg_total_relation_size(relid) DESC LIMIT 20;
Vacuum komutu çözüm olabilir, ama önce engeli kaldırın
Eğer uzun transactionlar vacuum’un eski satırları temizlemesini engelliyorsa, VACUUM çalıştırmak tek başına mucize yaratmaz. Önce idle in transaction oturumlarını ve uzun süren transactionları görmek gerekir.
Üretimde agresif bakım komutlarını çalıştırmadan önce yedekleme/PITR durumunu bilmek iyi bir alışkanlıktır. Çünkü performans bakımı çoğu zaman güvenli geri dönüş planıyla birlikte düşünülmelidir.
Vacuum’u engelleyebilecek transactionları bulma
SELECT pid, usename, state, now() - xact_start AS transaction_age, left(query, 160) AS query FROM pg_stat_activity WHERE xact_start IS NOT NULL ORDER BY transaction_age DESC LIMIT 20;
Daha güvenli bakım başlangıcı
VACUUM (ANALYZE, VERBOSE) orders; ANALYZE orders;
VACUUM FULL tabloyu kilitleyebilir; üretimde ancak planlı bakım ve geri dönüş hazırlığıyla düşünülmelidir.
Tekrarlamaması için uygulama davranışına bakın
Bloat yalnızca veritabanı ayarı değildir. Uygulama sürekli geniş satırları update ediyorsa, gereksiz transaction açık tutuyorsa veya soft-delete tablosu yıllarca temizlenmiyorsa vacuum hep arkadan yetişmeye çalışır.
TürkDB tarafında bakım penceresi, PITR ve gözlem akışı size güvenli zemin verir. Ama en kalıcı çözüm genellikle uygulamadaki transaction süresini kısaltmak ve veri yaşam döngüsünü netleştirmektir.