Denetim kayıtlarında olay tabloları için PostgreSQL bölümlendirme
Olay tabloları için PostgreSQL bölümlendirme: ne zaman işe yarar, bölüm anahtarı nasıl seçilir ve yönetici paneli filtreleri ile saklama politikalarını nasıl etkiler.

Neden olay ve denetim tabloları sorun olur
Olay tabloları ile denetim tabloları benzer görünür ama farklı amaçlarla vardırlar.
Olay tablosu olan biteni kaydeder: sayfa görüntülemeleri, gönderilen e-postalar, webhook çağrıları, iş çalıştırmaları. Denetim tablosu ise kim neyi ne zaman değiştirdiğini kaydeder: bir durum değişikliği, izin güncellemesi, ödeme onayı; genellikle “önce” ve “sonra” ayrıntılarıyla.
Her ikisi de ekleme-odaklı olduğu için hızla büyür. Nadiren tekil satırlar silersiniz ve yeni satırlar her dakika gelir. Arka plan işleri ve entegrasyonlar eklendiğinde küçük bir ürün bile haftalar içinde milyonlarca günlük satırı üretebilir.
Sorun günlük işte ortaya çıkar. Yönetici panelleri genelde “dün alınan hatalar” veya “bu kullanıcının yaptığı işlemler” gibi hızlı filtrelere ihtiyaç duyar. Tablo büyüdükçe bu temel ekranlar yavaşlamaya başlar.
Genelde önce birkaç belirtiyi görürsünüz:
- Dar bir tarih aralığıyla bile filtreler saniyeler sürer (veya zaman aşımına uğrar).
- İndeksler o kadar büyür ki eklemeler yavaşlar ve depolama maliyeti artar.
- VACUUM ve autovacuum daha uzun sürer, bakım fark edilir olur.
- Saklama riskli hale gelir: eski satırları silmek yavaştır ve bloat yaratır.
Bölümlendirme bununla başa çıkmanın bir yoludur. Basitçe söylemek gerekirse, tek bir büyük tabloyu (ana tablo) birçok daha küçük tabloya böler (partition'lar) ve bunlar tek bir mantıksal ad altında paylaşılır. PostgreSQL her yeni satırı genelde zaman bazlı bir kurala göre doğru partition'a yönlendirir.
Bu yüzden ekipler olay tabloları için PostgreSQL bölümlendirmesine bakar: güncel veriyi daha küçük parçalarda tutarak, PostgreSQL'in sadece ilgili partition'ları okumasını sağlar. Böylece “son 7 gün” gibi sorgular hızlanır ve saklama (eski veriyi atma) daha basit hale gelir.
Bölümlendirme sihirli bir hız düğmesi değildir. “Son 7 gün” gibi sorgular için çok yardımcı olabilir ve saklamayı kolaylaştırır (eski partition'ları düşürmek hızlıdır). Ama yeni sorunlar da çıkarabilir:
- Partition anahtarını kullanmayan sorgular birçok partition'ı kontrol etmek zorunda kalabilir.
- Daha fazla partition daha fazla nesne demektir; yönetim karmaşıklığı artar.
- Bazı benzersiz kısıtlamalar ve indeksler tüm veri üzerinde uygulamak açısından zorlaşır.
Eğer yönetici paneliniz tarih filtrelerine ve öngörülebilir saklama kurallarına dayanıyorsa, bölümlendirme gerçekten işe yarayabilir. Eğer çoğu sorgu “tüm geçmişte kullanıcı X'in tüm işlemlerini bul” ise, UI ve indeksleri dikkatle tasarlamazsanız sorun yaratabilir.
Log ve denetimlerde tipik erişim desenleri
Olay ve denetim tabloları tek bir yöne doğru büyür: yukarı. Sürekli yazma yapılır, neredeyse güncelleme olmaz. Çoğu satır bir kez yazılır, sonra destek işlerinde, olay incelemelerinde veya uyumluluk kontrollerinde okunur.
Bu “sadece ekleme” şekli önemlidir. Yazma performansı sürekli bir endişedir çünkü eklemeler gün boyu olur; okuma performansı ise destek veya operasyon gerektiğinde ani yoğunluklarda önem kazanır.
Çoğu okuma filtrelemeye dayanır, rastgele aramaya değil. Bir yönetici panelinde kullanıcı genelde genişten başlar (son 24 saat) sonra kullanıcı, varlık veya eylem bazında daraltır.
Yaygın filtreler şunlardır:
- Bir zaman aralığı
- Bir aktör (kullanıcı ID'si, servis hesabı, IP adresi)
- Bir hedef (varlık tipi + varlık ID, ör. Sipariş #1234)
- Bir eylem tipi (oluşturuldu, güncellendi, silindi, giriş başarısız)
- Bir durum veya şiddet (başarılı/hata)
Zaman aralığı doğal “ilk kesme”dir çünkü neredeyse her zaman vardır. Bu, olay tabloları için PostgreSQL bölümlendirmenin arkasındaki temel içgörüdür: birçok sorgu zaman dilimi ister ve diğer tüm filtreler o dilimin içinde ikinci düzey filtredir.
Saklama da diğer sabittir. Loglar nadiren sonsuza kadar saklanır. Ekipler genelde yüksek detaylı olayları 30 veya 90 gün tutar, sonra siler veya arşivler. Denetim logları daha uzun gereksinimlere (365 gün veya daha fazla) sahip olabilir, ama yine de eski veriyi engellemeden kaldırmanın öngörülebilir bir yolunu tercih edersiniz.
Denetim kaydı ayrıca ekstra beklentiler getirir. Genelde geçmişin değişmez olmasını, her kaydın izlenebilir olmasını (kim/ne/zaman artı istek veya oturum bağlamı) ve erişimin kontrol altında olmasını istersiniz (herkes güvenlikle ilgili olayları görmemeli).
Bu desenler doğrudan UI tasarımında görünür. İnsanların varsayılan olarak beklediği filtreler - tarih seçiciler, kullanıcı seçiciler, varlık arama, eylem açılır listesi - tablo ve indekslerinizin desteklemesi gereken aynı filtrelerdir; istenen yönetici deneyimini hacim arttıkça hızlı tutmak istiyorsanız bunlar gereklidir.
Bölümlendirmenin değip değmeyeceğini nasıl anlarsınız
Bölümlendirme denetim logları için otomatik en iyi uygulama değildir. Gündelik sorgular ve rutin bakım birbirine zıt çalışmaya başladığında işe yarar.
Basit bir boyut ipucu: bir olay tablosu on milyonlarca satıra ulaştığında ölçmeye başlamaya değer. Tablo ve indeksleri onlarca gigabayta ulaştığında, basit tarih aralığı aramaları bile yavaşlayabilir veya öngörülemez hale gelebilir çünkü diskten daha fazla veri sayfası okunur ve indeksler bakım açısından maliyetli hale gelir.
En açık sorgu sinyali: düzenli olarak küçük bir zaman dilimi (son gün, son hafta) istiyorsunuz ama PostgreSQL yine de tablonun büyük bir kısmına dokunuyor. Bunu “son etkinlik” ekranlarının yavaşlaması veya tarih + kullanıcı/eylem/varlık ID ile filtrelenmiş denetimlerde görürsünüz. Sorgu planlarında büyük taramalar veya buffer okuma oranları sürekli yüksekse, istemeden çok veri okuyorsunuz demektir.
Bakım sinyalleri de en az sorgu sinyalleri kadar önemlidir:
- VACUUM ve autovacuum eskisine göre çok daha uzun sürer.
- Autovacuum geride kalır ve ölü satırlar (bloat) birikir.
- İndeksler, özellikle çok-sütunlu indeksler beklenenden hızlı büyür.
- Bakım ile trafik örtüştüğünde kilitlenme (lock) problemleri belirginleşir.
Operasyonel maliyetler ekipleri bölümlendirmeye iten yavaş damladır. Yedekleme ve geri yükleme tek bir tabloyla yavaşlar, depolama artar ve saklama işleri büyük DELETE'ler yüzünden pahalı hale gelir.
Ana hedefleriniz temiz bir saklama politikası ve daha hızlı “son dönem” sorgularıysa, bölümlendirme genelde ciddi şekilde düşünmeye değerdir. Tablonuz orta boyda ve iyi indekslemeyle sorgular zaten hızlıysa, bölümlendirme karmaşıklık ekleyip net fayda sağlamayabilir.
Olay ve denetim tablolarına uygun bölümlendirme seçenekleri
Çoğu denetim ve olay verisi için en basit seçim zamanla aralık (range) bölümlendirmesidir. Loglar zaman sırasıyla gelir, sorgular genelde “son 24 saat” veya “son 30 gün” ile başlar ve saklama genelde zamana bağlıdır. Zaman partition'larıyla eski veriyi silmek, büyük DELETE'ler yapmak yerine eski partition'ı kaldırmak kadar basit olabilir.
Zaman aralığı bölümlendirme, indeksleri daha küçük ve odaklı tutar. Her partition'ın kendi indeksleri olur; böylece geçen hafta için bir sorgu yılları kapsayan devasa bir indeks üzerinde gezinmek zorunda kalmaz.
Diğer bölümlendirme stilleri de vardır ama log ve denetim vakalarına daha az uyar:
- List (tenant veya müşteri) küçük sayıda çok büyük tenant'ınız varsa ve sorgular genelde tek bir tenant içinde kalıyorsa işe yarayabilir. Yüzlerce veya binlerce tenant olduğunda ağrılı hale gelir.
- Hash (yazma yükünü eşit dağıtma) zaman penceresi sorgularınız yoksa ve yazmaları eşit dağıtmak istiyorsanız yardımcı olur. Denetim loglarında daha az yaygındır çünkü saklama ve zaman bazlı gezinmeyi zorlaştırır.
- Alt bölümlendirme (zaman + tenant gibi) güçlü olabilir ama karmaşıklık hızla artar. Yüksek hacimli ve sıkı tenant izolasyonu gerektiren sistemler içindir.
Zaman aralıklarını seçerseniz, partition boyutunu nasıl gezindiğinize ve sakladığınıza göre seçin. Çok yüksek hacim tabloları veya sıkı saklama için günlük partition'lar mantıklıdır. Orta hacimde yönetmesi kolay olduğu için aylık partition'lar uygundur.
Pratik bir örnek: bir yönetici ekibi her sabah başarısız giriş denemelerini kontrol edip son 7 günü filtreliyorsa, günlük veya haftalık partition'lar sorgunun yalnızca en güncel partition'lara bakmasını sağlar. PostgreSQL geri kalanları yok sayabilir.
Hangi yaklaşımı seçerseniz seçin, sıkıcı kısımları planlayın: gelecekteki partition'ları oluşturmak, geç gelen olaylarla başa çıkmak ve her sınırda ne olacağını tanımlamak (günün sonu, ayın sonu). Bölümlendirme, bu rutinler basit kaldığında değer verir.
Doğru bölüm anahtarı nasıl seçilir
İyi bir bölüm anahtarı tabloyu nasıl okuduğunuza uyar, şemadaki verinin nasıl göründüğüne değil.
Olay ve denetim logları için yönetici panelinden başlayın: insanlar hangi filtreyi ilk kullanıyor, neredeyse her zaman? Çoğu ekip için bu bir zaman aralığıdır (son 24 saat, son 7 gün, özel tarihler). Eğer bu sizin durumunuzsa, zaman bazlı bölümlendirme genelde en büyük ve öngörülebilir kazancı verir çünkü PostgreSQL seçilen aralığın dışındaki partition'ları atlayabilir.
Anahtarı uzun vadeli bir sözleme olarak düşünün. Yıllarca çalıştıracağınız sorgular için optimize ediyorsunuz.
İnsanların ilk filtre olarak kullandığıyla başlayın
Çoğu yönetici ekranı bir desen izler: zaman aralığı artı isteğe bağlı kullanıcı, eylem, durum veya kaynak. Sonuçları erken ve tutarlı şekilde daraltan şeyi partition anahtarı yapın.
Hızlı bir gerçeklik kontrolü:
- Varsayılan görünüm “son etkinlik” ise zaman damgası ile bölümlendirin.
- Varsayılan görünüm “bir tenant/hesap için olaylar” ise
tenant_idanlamlı olabilir, ama sadece tenant'lar yeterince büyükse. - İlk adım her zaman “bir kullanıcı seç” ise
user_idcazip gelebilir ama genelde yönetilemeyecek sayıda partitiona yol açar.
Yüksek kardinaliteli anahtarlardan kaçının
Bölümlendirme, her partition'ın anlamlı bir veri parçası olduğu durumlarda en iyi şekilde çalışır. user_id, session_id, request_id veya device_id gibi anahtarlar binlerce veya milyonlarca partitiona yol açabilir. Bu meta veri yükünü artırır, bakımı zorlaştırır ve planlamayı yavaşlatır.
Zaman bazlı partition'lar partition sayısını tahmin edilebilir tutar. Günlük, haftalık veya aylık arasında hacme göre seçim yaparsınız. Çok az partition (yılda biri) fazla fayda vermez. Çok fazla (saatlik) ise hızla yük getirir.
Doğru zaman damgasını seçin: created_at mı occurred_at mı
Zamanın ne anlama geldiği konusunda açık olun:
occurred_at: olayın ürün içinde gerçekleştiği zaman.created_at: veritabanının olayı kaydettiği zaman.
Denetimler için yöneticilerin çoğunlukla ilgilendiği "olayın olduğu" zamandır. Ama gecikmeli teslimat (çevrimdışı mobil istemciler, retry'ler, kuyruklar) varsa occurred_at geç gelebilir. Eğer geç gelen olaylar yaygınyse, created_at ile bölümlendirip occurred_at için indeks tutmak operasyonel olarak daha istikrarlı olabilir. Diğer seçenek, açık bir backfill politikası tanımlamak ve eski partition'ların ara sıra geç olaylar alabileceğini kabul etmektir.
Ayrıca zamanı nasıl sakladığınıza karar verin. Tutarlı bir tip kullanın (genelde timestamptz) ve UTC'yi tek kaynak olarak kabul edin. Görüntüleyicide izleyicinin saat dilimini kullanarak formatlayın. Bu, partition sınırlarını sabit tutar ve yaz saati uygulaması sürprizlerini önler.
Adım adım: bölümlendirmeyi planlayın ve uygulayın
Bölümlendirme küçük bir migrasyon projesi gibi ele alındığında en kolay haldedir, hızlı bir değişiklik gibi değil. Amaç basit yazmalar, öngörülebilir okumalar ve saklamanın rutin bir operasyon hâline gelmesidir.
Pratik bir uygulama planı
-
Hacminize uyan bir partition boyutu seçin. Ayda birkaç yüz bin satır olan tablolar için aylık partition genelde yeterlidir. Ayda on milyonlarca satır ekleniyorsa haftalık veya günlük partition'lar indeksleri küçük tutar ve vacuum işini sınırlı tutar.
-
Bölümlendirilmiş tablolar için anahtarları ve kısıtlamaları tasarlayın. PostgreSQL'de benzersiz bir kısıtlama partition anahtarını içermelidir (veya başka yollarla sağlanmalıdır). Yaygın bir desen
(created_at, id)şeklindedir; buradaidüretilir vecreated_atpartition anahtarıdır. Bu, daha sonra beklenmedik bir kısıtlama sorunu yaşamamanızı sağlar. -
Gelecekteki partition'ları ihtiyaç olmadan önce oluşturun. Partition olmayan bir satır için insert'in başarısız olmasını beklemeyin. Ne kadar öne partition oluşturacağınıza karar verin (örneğin 2-3 ay) ve bunu rutin bir iş haline getirin.
-
Partition başına indeksleri küçük ve kasıtlı tutun. Bölümlendirme indeksleri bedavaya getirmez. Çoğu olay tablosu partition anahtarına ek olarak bir veya iki indeks gerektirir; örneğin
actor_id,entity_idveyaevent_type. “Her ihtimale karşı” indekslerinden kaçının. Yeni partition'lara bunları ekleyebilir ve gerekirse eski partition'ları backfill edebilirsiniz. -
Saklamayı satır silmek yerine partition düşürmeye göre planlayın. Eğer 180 gün saklama yapıyorsanız, eski haftalık/aylık partition'ı düşürmek hızlıdır ve milyonlarca satırı silmekten kaçınır. Saklama kuralını, kimin çalıştıracağını ve başarıyı nasıl doğrulayacağınızı yazılı hale getirin.
Küçük örnek
Denetim tablonuz haftada 5 milyon satır alıyorsa, created_at üzerinde haftalık partition makul bir başlangıçtır. Partition'ları 8 hafta öncesine kadar oluşturun ve her partition için iki indeks tutun: birisi sık yapılan actor_id aramaları için, diğeri entity_id için. Saklama süresi dolduğunda en eski haftalık partition'ı düşürün, milyonlarca satırı silmeyin.
Eğer dahili araçları AppMaster içinde geliştiriyorsanız, bölüm anahtarını ve kısıtlamaları erken belirlemek veri modeli ve üretilen kodun aynı varsayımları takip etmesine yardımcı olur.
Bölümlendirmenin yönetici paneli filtreleri için değiştirdikleri
Bir günlük tablosunu bölümlendirdikten sonra yönetici paneli filtreleri “sadece UI” olmaktan çıkar. Sorgunun kaç partition'a dokunacağını belirleyen ana faktör hâline gelirler.
En büyük pratik değişim: artık zaman isteğe bağlı olamaz. Kullanıcılar sınırsız bir arama çalıştırabiliyorsa (tarih aralığı olmadan sadece “kullanıcı X için her şey”), PostgreSQL her partition'ı kontrol etmek zorunda kalabilir. Her kontrol hızlı olsa bile birçok partition açmak ek yük getirir ve sayfa yavaş hissedilir.
İyi bir kural: log ve denetim aramalarında zaman aralığını zorunlu kılın ve mantıklı bir varsayılan atayın (ör. son 24 saat). Birinin gerçekten “tüm zamanlar”a ihtiyacı varsa bunu kasıtlı bir tercih haline getirip yavaş olabileceği konusunda uyarın.
Filtreleri partition pruning ile uyumlu yapın
Partition pruning sadece WHERE ifadesi partition anahtarını PostgreSQL'in kullanabileceği şekilde içerdiğinde yardımcı olur. created_at BETWEEN X AND Y gibi filtreler pruning yapar. Sıklıkla pruning'i bozan desenler arasında timestamp'ı date'e cast etmek, kolonu fonksiyon içinde sarmak veya partition anahtarından farklı bir zaman alanını filtrelemek bulunur.
Her partition içinde indeksler insanların gerçekten nasıl filtrelediğiyle eşleşmelidir. Pratikte genelde önemli olan kombinasyonlar zaman artı bir başka koşuldur: tenant/workspace, kullanıcı, eylem/tip, varlık ID'si veya durum.
Sıralama ve sayfalandırma: sığ tutun
Bölümlendirme tek başına yavaş sayfalandırmayı çözmez. Yönetici paneli en yeniye göre sıralıyor ve kullanıcı 5000. sayfaya atlıyorsa, derin OFFSET sayfalandırma hâlâ PostgreSQL'in çok sayıda satırı atlamasını gerektirir.
İmleç tarzı sayfalandırma loglar için genelde daha iyidir: “bu (timestamp, id)'den önceki olayları yükle.” Bu, veritabanının indeksleri kullanmasını sağlar ve büyük OFFSET'lerin neden olduğu geçişleri engeller.
Ayrıca ön ayarlar yardımcı olur: birkaç seçenek genelde yeterlidir: son 24 saat, son 7 gün, bugün, dün, özel aralık. Ön ayarlar kazara "her şeyi tarama" sorgularını azaltır ve yönetici deneyimini daha öngörülebilir kılar.
Yaygın hatalar ve tuzaklar
Çoğu bölümlendirme projesi basit nedenlerden başarısız olur: bölümlendirme kendisi çalışır ama sorgular ve yönetici UI buna uymadığı için fayda görülmez. Bölümlendirmeden yararlanmak istiyorsanız, gerçek filtreler ve gerçek saklama üzerine tasarlayın.
1) Yanlış zaman sütununda bölümlendirme
Partition pruning sadece WHERE ifadesi partition anahtarıyla eşleştiğinde olur. Yaygın hata created_at ile bölümlendirmek ama yönetici panelinin event_time ile filtrelemesidir. Destek ekibiniz genelde "10:00 ile 10:15 arasında ne oldu" diyorsa ama tablo ingestion zamanına göre bölümleniyorsa yine beklenenden fazla veri okunabilir.
2) Çok küçük partition'lar oluşturmak
Saatlik (veya daha küçük) partition'lar düzenli görünse de ek yük getirir: yönetilecek daha fazla nesne, sorgu planlayıcısı için ek iş ve eksik indeks veya izin eşleşmeleri için daha fazla şans.
Aşırı yazma hacmi ve sıkı saklama yoksa günlük veya aylık partition'lar genelde daha kolay işletilir.
3) “Global benzersizlik”nin hala çalışacağını varsaymak
Partitioned tabloların kısıtlamaları vardır: bazı benzersiz indeksler partition anahtarını içermelidir, aksi halde PostgreSQL bunları tüm veriye karşı zorlayamaz.
Bu, ekipleri event_id'nin sonsuza kadar benzersiz olacağını beklerken şaşırtır. Eğer küresel bir benzersiz kimliğe ihtiyacınız varsa UUID kullanın ve bunu dikkatle yönetin veya uygulama katmanında benzersizliği sağlayın.
4) Yönetici UI'sının geniş aramalar çalıştırmasına izin vermek
Yönetici panelleri genelde filtre olmadan çalışan dostça bir arama kutusuyla gelir. Bir bölümlendirilmiş günlük tablosunda bu, her partition'ı taramak anlamına gelebilir.
Mesaj gövdeleri üzerinde serbest metin arama özellikle risklidir. Kısıtlamalar koyun: zaman aralığı gerektirin, varsayılan aralığı sınırlandırın ve “tüm zamanlar”ı bilinçli bir seçenek haline getirin.
5) Saklama planı olmaması (ve partition yönetimi planı olmaması)
Bölümlendirme saklamayı otomatik olarak çözmez. Politika yoksa elinizde eski partition'larla dolu, karışık depolama ve daha yavaş bakım kalır.
Basit bir işletme kuralları seti bunu önler: ham olayların ne kadar süre tutulacağı, gelecekteki partition'ların otomatik oluşturulması ve süresi dolanların otomatik düşürülmesi, indekslerin tutarlı uygulanması, partition sayısı ve sınır tarihleri izleme ve en yavaş yönetici filtrelerini gerçekçi veri hacimleriyle test etme.
Commit etmeden önce hızlı kontrol listesi
Bölümlendirme denetim loglarında büyük kazanç sağlayabilir ama rutin iş ekler. Şemayı değiştirmeden önce insanların tabloyu gerçekten nasıl kullandığını kontrol edin.
Eğer ana sıkıntınız biri “Yönetici sayfaları biri ‘Son 24 saat’ veya ‘Bu hafta’ açtığında zaman aşımına uğruyor” ise, uygun bir adayla karşı karşıyasınız. Eğer çoğu sorgu “tüm geçmiş için kullanıcı ID” ise, UI aramaları yönlendirmedikçe bölümlendirme daha az yardımcı olabilir.
Ekipleri dürüst tutacak kısa bir kontrol listesi:
- Zaman aralığı varsayılan filtredir. Çoğu yönetici sorgusu açık bir pencere (from/to) içerir. Açık uçlu sorgular yaygınsa partition pruning daha az yardımcı olur.
- Saklama partition düşürmeyle uygulanır, satır silmeyle değil. Eski partition'ı düşürmekten rahat olun ve ne kadar veri tutulacağını netleştirin.
- Partition sayısı makul kalır. Yıllık tahmini partition sayısını hesaplayın (günlük, haftalık, aylık). Çok küçük partition sayısı yükü artırır, çok büyük olan faydayı azaltır.
- İndeksler insanların gerçekten kullandığı filtrelerle eşleşir. Partition anahtarının yanında, yaygın filtreler ve sıralama için partition başına uygun indeksler gerekir.
- Partition'lar otomatik oluşturulur ve izlenir. Gelecekteki partition'ları oluşturan rutin bir iş olsun ve başarısızlığı fark edin.
Pratik bir test: destek veya operasyon ekibinizin en çok kullandığı üç filtreye bakın. Eğer ikisi genelde “zaman aralığı + bir koşul” ile karşılanıyorsa, PostgreSQL bölümlendirmesi olay tabloları için ciddi şekilde değerlendirmeye değerdir.
Gerçekçi bir örnek ve pratik sonraki adımlar
Bir destek ekibi iki ekranı sürekli açık tutar: “Giriş etkinlikleri” (başarılı ve başarısız girişler) ve “Güvenlik denetimleri” (şifre sıfırlamalar, rol değişiklikleri, API anahtarı güncellemeleri). Müşteri şüpheli bir aktivite bildirdiğinde ekip kullanıcıyı filtreler, son birkaç saati kontrol eder ve kısa bir rapor çıkarır.
Bölümlendirme öncesinde, her şey tek events tablosunda durur. Hızla büyür ve basit aramalar bile eski satırlarla uğraşmak zorunda kaldığı için ağırlaşır. Saklama de zordur: gece yapılan görev eski satırları siler, fakat büyük DELETE'ler uzun sürer, bloat yaratır ve normal trafikle yarışır.
Olay zamanına göre aylık bölümlendirmeden sonra iş akışı iyileşir. Yönetici paneli zaman filtresini zorunlu kıldığından çoğu sorgu yalnızca bir veya iki partition'a dokunur. Sayfalar daha hızlı yüklenir çünkü PostgreSQL seçilen aralığın dışındaki partition'ları yok sayar. Saklama rutinleşir: milyonlarca satırı silmek yerine eski partition'ı düşürürsünüz.
Yine de zor kalan bir şey vardır: “tüm zamanlar” üzerinde serbest metin arama. Birisi bir IP adresi veya tarih limiti olmadan belirsiz bir ifade arıyorsa, bölümlendirme bunu ucuz yapamaz. Çözüm genelde üründe: aramaları varsayılan olarak bir zaman penceresine sınırlamak ve “son 24 saat / 7 gün / 30 gün” seçeneklerini belirgin yapmak.
İşleyen pratik sonraki adımlar:
- Önce yönetici paneli filtrelerinizi haritalayın. İnsanların hangi alanları kullandığını ve hangilerinin zorunlu olması gerektiğini yazın.
- Nasıl gezindiğinize uygun partition'ları seçin. Aylık partition'lar genelde iyi bir başlangıçtır; hacim zorladıkça haftalığa geçin.
- Zaman aralığını birinci sınıf filtre yapın. UI “tarihsiz” arama izin veriyorsa yavaş sayfalar bekleyin.
- İndeksleri gerçek filtrelerle hizalayın. Zaman her zaman varsa, zaman-öncelikli indeks stratejisi genelde doğru tabandır.
- Saklama kurallarını partition sınırlarıyla hizalayın (ör. 13 ay tut ve daha eskiyi düşür).
Eğer AppMaster (appmaster.io) ile iç yönetici paneli inşa ediyorsanız, bu varsayımları erken modellemek faydalıdır: zaman sınırlı filtreleri veri modelinin bir parçası olarak görün, sadece UI tercihi olarak değil. Bu küçük karar log hacmi büyüdükçe sorgu performansını korur.
SSS
Bölümlendirme, yaygın sorgularınız zaman bazlı kısıtlıysa (ör. “son 24 saat” veya “son 7 gün”) ve tablo öyle büyük ki indeksler ve bakım zahmetli hale geliyorsa en işe yarar. Eğer ana sorgularınız “kullanıcı X için tüm geçmiş” ise, UI’de zaman filtrelerini zorunlu kılmadıkça bölümlendirme ek yük getirebilir.
Loglar ve denetimler için varsayılan olarak zaman aralığına göre (range) bölümlendirme en iyi seçenektir: yazmalar zaman sırasıyla gelir, sorgular genelde zaman penceresiyle başlar ve saklama genellikle zamana bağlıdır. Liste veya hash yalnızca özel durumlarda işe yarar ama genelde saklamayı ve taramayı zorlaştırır.
Kullanıcıların önce ve neredeyse her zaman filtrelediği alanı seçin. Çoğu yönetici panelinde bu bir zaman aralığıdır; bu yüzden zaman bazlı bölümlendirme en öngörülebilir seçimdir. Bölüm anahtarını değiştirmek ciddi bir migrasyon gerektirebileceği için uzun vadeli bir taahhüt olarak düşünün.
Zaman damgası veya tenant kimliği gibi yönetilebilir sayıda bölüm üreten anahtarları kullanın. user_id gibi yüksek kardinaliteli anahtarlar binlerce bölüm oluşturabilir, planlayıcı ve işletme yükünü artırır ve genelde tutarlı hız kazançları sağlamaz.
Gecikmeli teslimatlar (kuyruklar, yeniden denemeler, çevrimdışı istemciler) yaygınsa ve operasyonel kararlılık istiyorsanız created_at ile bölümlendirin. Gerçek olay zamanına (ör. occurred_at) göre sorularınızın çoğuysa ve olay zamanı güvenilirse occurred_at ile bölümlendirin. Orta yol olarak created_at ile bölümlendirip occurred_at üzerinde indeks tutmak sık kullanılan bir yaklaşımdır.
Evet. Bir tablo bölümlendirildiğinde yönetici panellerinin çoğunda zaman aralığını zorunlu kılmak iyi bir fikirdir. Zaman filtresi olmayan sorgular çok sayıda bölümü kontrol etmeyi gerektirebilir ve sayfalar yavaşlar. İyi bir varsayılan “son 24 saat” olurken, “tüm zamanlar” bilinçli ve uyarılı bir seçim olmalı.
Evet. Bölüm anahtarını fonksiyon içinde sarma (ör. timestamp'ı date'e cast etmek) veya bölüm anahtarından farklı bir zaman sütununu filtrelemek gibi desenler pruning'i bozabilir. created_at BETWEEN X AND Y gibi basit formlar pruning'i güvenilir kılar.
Derin OFFSET ile sayfalandırmadan kaçının; büyük sayfalarda veritabanı çok sayıda satırı atlamak zorunda kalır. timestamp ve id kombinasyonuyla “bu tarihten önceki olayları yükle” tarzı imleç (cursor) tabanlı sayfalandırma, indeks dostu kalır ve ölçeklendikçe performansı korur.
PostgreSQL'de bazı benzersiz kısıtlamalar bölüm anahtarını içermelidir; aksi halde tüm bölümler üzerinde küresel benzersizlik garanti edilmez. Pratikte (created_at, id) gibi bileşik benzersizlikler veya dışa dönük benzersiz kimlik için UUID kullanımı yaygındır. Küresel benzersizliği uygulama katmanında yönetmek de bir seçenektir.
Eski bölümleri silmek hızlıdır ve büyük DELETE işlemlerinin yarattığı bloat ve fazla vacuum işinden kaçınır. Anahtar, saklama kurallarını bölüm sınırlarıyla hizalamaktır: gelecekteki bölümleri otomatik oluşturun ve süresi dolanları programlı olarak düşürün.


