SQLProgramlamaKıdemli Veritabanı Mühendisi

**PostgreSQL** MVCC uygulanmasının yüksek değişim tablolarında hangi özel işlemler sırasında tüp şişkinliği oluşturduğunu ve **VACUUM** performans düşüşünü azaltmak için **PARTITIONING** ile nasıl bir tablo yapısı tasarımı yapacağınızı açıklar mısınız?

Hintsage yapay zeka asistanı ile mülakatları geçin

Sorunun cevabı

PostgreSQL, verileri yerinde yazmak yerine her GÜNCELLEME ve SİLME işlemi için yeni satır sürümleri oluşturarak Çok Versiyonlu Eşzamanlılık Kontrolü (MVCC) uygulamasını gerçekleştirir. Bu tasarım okuma kilitlerini ortadan kaldırır ancak yığın içinde onarılması gereken "ölü tüpler" bırakır; bu, VACUUM işlemi ile gerçekleştirilir. Bir tablo yüksek değişim iş yükleri yaşadığında—örneğin, bekleyen kayıtlar üzerindeki sık durum güncellemeleri veya yumuşak silme geçişleri—ölü tüplerin birikimi vacuum işlemlerini geçersiz kılarak tablo şişkinliğine, indeks şişkinliğine ve sorgu performansının düşmesine yol açar.

Temel sorun, VACUUM'un tüm tabloyu taraması gerektiğidir, bu da monolitik çok terabaytlık tablolarda bu işlemi G/Ç açısından sınırlı hale getirebilir ve işlem ID’nin sarılması öncesinde tamamlanamamasıyla sonuçlanabilir. Müdahale olmaksızın, tablo sürekli büyümeye devam ederken, fiili satır sayısı sabit kalmakta, aşırı depolama alanı tüketmekte ve indeks taramalarını yavaşlatmaktadır.

Çözüm, RANGE stratejisi kullanarak Açıklamalı Bölme uygulamak olacaktır; bu, yaratım tarihi gibi zamansal veya mantıksal bir anahtarla tabloyu daha küçük fiziksel partisyonlara (örneğin, aylık segmentler) bölerek vacuum işlemlerinin tüm tablo yerine bireysel partisyonlar üzerinde gerçekleştirilmesini sağlar. Ayrıca, PARTITION PRUNING, sorguların yalnızca ilgili segmentlere erişmesini sağlarken, yaşlı partisyonlar ayrılıp arşivlenebilir ve bu da vacuum maliyeti olmadan depolama alanını anında geri kazandırır.

-- Aralık bölme ile ana tablo CREATE TABLE iot_sensor_data ( sensor_id INT NOT NULL, temperature NUMERIC, recorded_at TIMESTAMP NOT NULL, status VARCHAR(20) ) PARTITION BY RANGE (recorded_at); -- Güncel yüksek değişim verileri için aylık bölüm CREATE TABLE iot_sensor_data_2024_06 PARTITION OF iot_sensor_data FOR VALUES FROM ('2024-06-01') TO ('2024-07-01'); -- Bölüm anahtarı üzerinde indeks CREATE INDEX idx_sensor_date ON iot_sensor_data (recorded_at);

Hayattan bir durum

Bir akıllı üretim müşterisi, 50,000 IoT sensöründen telemetri alarak her gün 10 milyon okuma üreten bir PostgreSQL 14 veritabanı çalıştırıyordu; bunların %30'u 24 saat içinde durum güncellemeleri gerektiriyordu. sensor_logs tablosu, sürekli durum bayrağı güncellemeleri nedeniyle ölü tüpleri geri kazanacak kadar hızlı işlenemediği için altı ayda 2TB'a patladı. Sorgu gecikmesi 30 saniyeye yükseldi ve pg_class, tablonun mantıksal boyutuna göre %400 şişkin olduğunu ortaya çıkardı.

Üç mimari çözüm değerlendirildi. İlk yaklaşım, VACUUM ayarlarını agresif bir şekilde ayarlamak, autovacuum_vacuum_scale_factor'ı 0.02'ye düşürmek ve maintenance_work_mem'i 2GB'a artırmaktı. Bu, marjinal olarak yardımcı oldu ancak işlem sürekli olarak 2TB'lık tabloyu taramayı gerektirdi ve üretim sorguları ile yoğun G/Ç çatışması yol açarak gece bakım pencerelerinde tamamlanamadı. İkinci strateji, eski verileri hariç tutan KISMİ İNDİSLER önermektedir, bu durum indeks şişkinliğini azalttı ancak tablodaki temel yığın şişkinliğini veya ölü tüp birikimini ele almadı.

Üçüncü çözüm, recorded_at zaman damgası üzerinde RANGE ile Açıklamalı Bölme uygulamasıydı ve her biri yaklaşık 300GB olan aylık partisyonlar oluşturuldu. Bu yaklaşım, yüksek değişim faaliyetini mevcut ay bölmesine lokalize ettiği için seçildi; bu durum VACUUM'un her çalışmada 2TB yerine 300GB'ı işleyebilmesine olanak tanıdı. Ayrıca, bir yılı geçen partisyonlar AYRILDI ve soğuk depolamaya taşındı, böylece maliyetli SİLME işlemleri olmadan alan geri kazanıldı. Uygulama sonrası vacuum süresi 8 saatten 45 dakikaya düştü, işlem ID sarılma riski ortadan kalktı ve sorgu performansı 10 kat iyileşti.

Adayların Sıkça Gözden Kaçırdığı Noktalar

PostgreSQL'in HOT (Yığın-Sadece Tüp) mekanizması indeks şişkinliğini nasıl azaltır ve hangi belirli koşulda uygulanmaz?

HOT güncellemeleri, bir satır güncellendiğinde ancak herhangi bir indekslenmiş sütunun değiştirilmediği ve aynı 8KB veri sayfasında yeterli boş alan bulunduğu durumlar için geçerlidir. Bu durumda, PostgreSQL yeni tüpü yığında eski tüpe ekleyerek indeks girdileri oluşturmadan işlem yapar ve bu da indeks bakım yükünü önemli ölçüde azaltır. Ancak, güncellemenin herhangi bir indekste bulunan sütunu değiştirmesi durumunda veya sayfanın fillfactor eşiğinin altındaki boş alanı yoksa, HOT hemen başarısız olur ve PostgreSQL yeni indeks göstergelerini yazmak zorunda kalır, bu da şişkinliğe yol açar. Adaylar genellikle tüm GÜNCELLEME işlemlerinin indeksleri eşit şekilde etkilediğini varsayar, HOT'un başarılı olduğu durumlarda indekslenmemiş sütunları güncellemenin önemli ölçüde daha ucuz olduğunu anlamaz.

VACUUM, VACUUM FULL ve CLUSTER arasındaki hassas fark nedir? Kilitleme davranışı ve tablo kullanılabilirliği açısından?

VACUUM, tüm işlemlerle eş zamanlı çalışarak ölü tüpleri yeniden kullanılabilir alan olarak işaretler, işletim sistemine depolama alanı geri vermez; kullanıcı verileri üzerinde hiçbir kilit tutmaz. VACUUM FULL, şişkinliği tamamen ortadan kaldırmak için tüm tablo dosyasını yeniden yazar ancak tüm okuma ve yazmaları engelleyen bir ACCESS EXCLUSIVE kilidi alır; bu işlem büyük tablolarda saatler sürebilir. CLUSTER, tabloyu bir indeks sırasına göre fiziksel olarak yeniden düzenler; bu da yine bir ACCESS EXCLUSIVE kilidi gerektirir ve saf alan geri kazanımı için genelde VACUUM FULL'dan daha yavaştır ancak gelecekteki kümelenmiş indeks taramaları için sıralı düzeni korur. Adaylar genelde rutin bakım için tehlikeli bir şekilde VACUUM FULL'ı önerir; bunun, tabloyu tamamen kullanılamaz hale getirdiğini anlamazlar.

Görünürlük haritası indeks-sadece tarama performansını nasıl etkiliyor ve bu erişim yöntemi için vacuum sıklığının önemi nedir?

Görünürlük haritası, tüm mevcut ve gelecekteki işlemler için yalnızca görülebilen tüpleri içeren yığın sayfalarını izleyen, tablonun yanında saklanan ikili bir bitmap'tir. Bir İNDİS-Sadece TARAMA, yalnızca indeks ve görünürlük haritasını kullanarak sorguları yerine getirebilir, ancak yalnızca harita sayfanın üzerindeki tüm satırların görünür olduğunu onaylarsa mümkündür. Eğer bir sayfada herhangi bir ölü tüp veya onaylanmamış işlemler varsa, görünürlük biti kaldırılır ve veritabanı bireysel yığın tüplerini doğrulamak zorunda kalır. Sık VACUUM, görünürlük haritası bitlerini güncelleyerek gerçek indeks-sadece erişimi sağlarken, bunun olmaması durumunda, kapsayıcı indeksleri kullanan sorgular bile tüp görünürlüğünü kontrol etmek için rastgele G/Ç yaparak optimizasyonun amacını bozar.