Postgres'te DELETE İşlemleri Gerçekten Nasıl Ölçeklenebilir?
Kaynak: Hacker News
İçindekiler 2 başlık
PostgreSQL'de DELETE komutunun yüksek performanslı sistemlerde kötü bir şöhreti vardır. Birçok büyük ölçekli mimari, satır bazlı silme işlemlerinden tamamen kaçınarak verileri temizlemek için tabloları tamamen boşaltmayı (TRUNCATE) veya bölümleri (partition) düşürmeyi tercih eder. Ancak verilerin heterojen olduğu ve bazı kayıtların diğerlerinden daha uzun süre saklanması gereken senaryolarda DELETE, tablo veya bölüm silmeye kıyasla çok daha yüksek bir esneklik sunar.
Bir tablodaki her satırı tek tek silmek, işlem güvenliğini (transactional safety) sağlayan ağır mekanizmalar nedeniyle tabloyu doğrudan düşürmekten katbekat daha yavaştır. Yine de doğru önbellek (cache) ve indeks optimizasyonlarıyla, saniyede on binlerce dayanıklı iş akışı (durable workflows) ve kuyruk adımı işleyen sistemlerde bile veri saklama politikalarını uygulamak için DELETE işlemini ölçeklendirmek mümkündür.
Postgres Bir Satırı Nasıl Siler?#
Postgres'te silme işlemlerinin neden maliyetli olduğunu anlamak için arka plandaki mimariyi incelemek gerekir. Bir satırı sildiğinizde, veritabanı bu satırı fiziksel olarak hemen silmez. Bunun temel nedeni işlem izolasyonu (transaction isolation) sağlamaktır: Silme işleminiz siz COMMIT edene kadar diğer işlemlere görünmemelidir.
Postgres bu durumu Çok Sürümlü Eşzamanlılık Kontrolü (MVCC) ile yönetir:
- Bir satır her güncellendiğinde, tabloya ve indekslere güncellenmiş veriyi içeren yeni bir satır sürümü eklenir.
- Her sürüm, onu oluşturan işlemin kimliği (transaction ID) ve onu geçersiz kılan işlemin kimliği ile damgalanır.
- Bir satırı sildiğinizde Postgres, son sürümü sizin işlem kimliğinizle damgalar ve böylece satırı sonraki işlemler için görünmez hale getirir.
- Bu tasarım, uzun süreli işlemlerin tutarlı bir veri "anlık görüntüsüne" (snapshot) erişmesine olanak tanır.
MVCC mimarisinin kaçınılmaz bir sonucu veri devridaimi (churn) oluşmasıdır. Her güncelleme ve silme işlemi, disk alanını geri kazanmak için bir noktada fiziksel olarak temizlenmesi gereken "ölü satırlar" (dead tuples) üretir. Postgres bu ölü satırları, periyodik olarak çalışan autovacuum aracılığıyla VACUUM işlemiyle temizler. Milyonlarca iş akışı verisini düzenli olarak silmesi gereken dayanıklı yürütme sistemlerinde bu MVCC yükü, önbellekleme ve indekslerle karmaşık şekillerde etkileşime girerek silme maliyetini görünenden çok daha yüksek hale getirir.
Yerellik (Locality) Sorunu ile Mücadele#
İş akışı silme işlemleri genellikle belirli bir veri saklama politikasını (retention policy) takip eder. Örneğin kullanıcı, "bir haftadan daha önce tamamlanmış tüm iş akışlarını sil" şeklinde bir kural tanımlar ve sistem motoru bu kuralı periyodik olarak uygular.
Yazılım geliştirme ve veritabanı mühendisliği açısından bu süreçten çıkarılması gereken temel pratik dersler şunlardır:
- Esneklik ve Maliyet Dengesi: Yaşam döngüsü birbirinden farklı verileri aynı tabloda tutuyorsanız
DROP PARTITIONyerine optimize edilmişDELETEstratejilerine odaklanmalısınız. - MVCC ve Autovacuum Farkındalığı: Yoğun silme işlemi yapan uygulamalarda ölü satırların (
dead tuples) indeks şişmesine ve önbellek verimsizliğine yol açacağını hesaba katarakVACUUMyapılandırmalarını iş yükünüze göre ayarlamalısınız. - Veri Yerelliği (Locality): Zamana dayalı saklama politikaları uygularken, silinecek verilerin disk ve önbellek üzerindeki dağılımının (locality) sorgu ve indeks performansını doğrudan etkilediğini unutmamalısınız.
Kaynak ve atıf
Bu yazı, Hacker News üzerinde yayımlanan içerikten yararlanılarak Edumints tarafından yapay zekâ desteğiyle Türkçe hazırlandı. Ayrıntılar ve yazarların kendi anlatımı için orijinaline bakabilirsin:
- dbos.dev/blog/scaling-deletions-in-postgres