<

Veritabanında Milyon Kayıt: Partisyonlama ve Arşivleme Stratejileri

Kendi araç takip sistemimizde tek bir konum tablosu yılda yüz milyonlarca kayıt üretir; araç başına 30 saniyede bir konum yazarsanız matematik sizi oraya götürür. Geçen ay da bir müşterimizden şu telefonu aldık: "Gece çalışan temizlik script'i sabaha kadar bitmemiş, tablo kilitli kalmış, sabah operasyon durdu." Sorun neydi? 400 milyon satırlık tablodan DELETE ile üç yıllık veri silmeye çalışmak. Bu iki hikâye aynı dersin iki yüzü: belli bir ölçekten sonra "index atarız, hallolur" devri kapanıyor. Büyük tabloyla yaşamanın olgun üç stratejisi var — partisyonlama, arşivleme ve en baştan doğru kurgulanmış veri yaşam döngüsü — ve bu yazıda üçünü de sahadan örneklerle anlatacağım.

Önce dürüst soru: bu veri neden hâlâ burada?

Teknik çözüme atlamadan önce sorulması gereken soru bu. Sorgularınızın %99'u son 3 ayın verisini istiyorsa, 5 yıllık ham kaydı operasyonel tabloda tutmak herkese kesilen bir cezadır: sorgular yavaşlar, indeksler belleğe sığmaz, yedekler saatler sürer, felaket kurtarma süresi uzar.

Biz her projede veriyi üç sıcaklıkta sınıflandırıyoruz. Sıcak veri, günlük operasyonun kullandığı dilim — araç takipte son birkaç ayın konumları. Ilık veri, raporlamanın ara sıra döndüğü dönem — geçen yılın kıyas raporları gibi. Soğuk veri ise neredeyse hiç okunmayan ama yasal saklama süresi dolmadığı için atılamayan kısım. Bu üç katmanın aynı depoda, aynı maliyetle, aynı performans beklentisiyle tutulması için hiçbir mühendislik gerekçesi yok. Katmanlar ayrılınca çözümler de kendiliğinden netleşiyor.

Partisyonlama: tek tablo, çok çekmece

MySQL ve PostgreSQL'de tabloyu tarihe göre — bizim pratiğimizde neredeyse hep aylık RANGE ile — bölmek, mantıksal olarak tek tablo görüntüsünü korurken fiziksel olarak veriyi çekmecelere ayırır. "Ekim ayının rolanti raporu" sorgusu artık 400 milyon satırı değil, yalnızca ekim çekmecesini tarar; buna partition pruning deniyor ve doğru kurulduğunda etkisi dramatiktir.

Ama partisyonlamanın asıl süper gücü sorguda değil, bakımda ortaya çıkar. Baştaki müşterimizin sabaha kadar süren DELETE faciasını hatırlayın: partisyonlu tabloda aynı iş, DROP PARTITION ile saniyeler sürer. Kilit yok, undo log şişmesi yok, replikasyon gecikmesi yok. Milyonlarca satırı tek tek silmekle çekmeceyi komple çıkarıp atmak arasındaki fark bu. O müşteride tabloyu aylık partisyonlara geçirdik; eskiden geceyi yiyen temizlik işi artık cron'da birkaç saniyelik bir satır.

Motor farklarına da kısaca değineyim. PostgreSQL'in bildirimsel partisyonlaması son sürümlerde ciddi olgunlaştı; MySQL tarafında RANGE partisyon yıllardır kararlı çalışıyor. Ama iki motorun kısıtları farklıdır — mesela benzersiz indekslerin partisyon anahtarını içerme zorunluluğu gibi kurallar tasarımınızı beklemediğiniz yerden şekillendirir. Hangi motordaysanız planı o motorun gerçek kısıtlarıyla, üretim benzeri veriyle test edin; kavramlar ortak, ayrıntılar değil.

Bir uyarıyı büyük harflerle yazmam lazım: partisyon anahtarı sorgularınızda geçmiyorsa pruning çalışmaz ve bütün bu mimariden hiçbir kazanç elde edemezsiniz — hatta bazı sorgular yavaşlar bile. Tarihe göre böldüyseniz ama raporlarınız hep müşteri numarasıyla süzüyorsa, veritabanı yine bütün çekmeceleri açıp bakmak zorunda kalır. Anahtar seçimi sorgu deseninize göre yapılır; modaya, bloga, komşunun projesine göre değil. Partisyonlamaya karar vermeden önce en çok çalışan 20 sorgunuzu çıkarıp WHERE koşullarına bakın — kararı o liste verir.

İndeks tarafındaki kazanç da hesaba yazılmalı: partisyonlu tabloda her çekmecenin kendi indeksi olur ve aktif ayın indeksi rahatça belleğe sığar. 400 milyon satırlık tek bir indeksin bellekte yaşama şansı yokken, 8 milyon satırlık ay indeksi orada gayet mutlu yaşar; ekleme hızındaki rahatlama da cabası. Bizim konum tablolarında yazma performansı, partisyona geçişten sonra gözle görülür düzeldi.

Arşiv dediğin sorgulanabilir olmalı

Soğuk katman için reçetemiz: veriyi sıkıştırılmış sütunsal formatta (Parquet bizim standardımız) nesne depolamaya taşımak ve operasyonel veritabanından silmek. Kazanç iki koldan gelir — depolama maliyeti kat kat düşer (sıkıştırma oranları konum verisi gibi tekrarlı veride gerçekten etkileyici) ve operasyonel veritabanı küçüldüğü için yedekleme, replikasyon, bakım işlemlerinin tamamı hızlanır.

Kritik kural şu: arşiv, "yazıp unuttuğumuz yer" değil, sorgulanabilir bir katman olmalı. Yasal bir talep geldiğinde — ve araç takip dünyasında geliyor; kaza tespiti, ihtilaf, denetim — 2019'un kayıtlarını makul sürede açıp sunabilmelisiniz. Parquet dosyaları üzerinde sorgu koşturan araçlar bugün gayet olgun; arşivden veri çekmek zevkli olmak zorunda değil ama mümkün olmak zorunda.

Saklama politikasının bir de hukuk boyutu var. Kişisel veri niteliğindeki kayıtlar için KVKK "gerekenden uzun tutmayın" der; sektörel mevzuat ise kimi veriyi yıllarca saklamanızı ister. Yani "her şeyi sonsuza kadar tutalım" da "eskiyi hemen silelim" de hukuken riskli olabilir. Politikayı yazarken masada hukuk danışmanınız da otursun; biz müşteri projelerinde bu toplantıyı işin en başına koyduruyoruz, çünkü teknik mimari bu cevaplara göre şekilleniyor.

Bir de herkesin başına gelen şu tuzağı analım: arşive taşıma işi yazılır, çalışır, unutulur — ve bir gün taşımanın aylardır sessizce hata verdiği anlaşılır. Arşiv işiniz izlemesiz çalışmasın; "bu ay kaç satır taşındı" metriği bir panoda dursun.

Sıfırdan kuruyorsanız birinci günden yapın

Bütün bu anlattıklarımın en ucuz hali, tablo daha 10 bin satırken kurulanıdır. Bizim yeni projelerdeki reçetemiz dört adım halinde işliyor. Önce saklama politikası yazılıyor: hangi veri, ne kadar süre, hangi katmanda — bu bir mühendislik dokümanı olduğu kadar hukuki bir dokümandır ve müşteriyle birlikte imzalanır. Zaman serisi karakterindeki her tablo (konum, log, olay, ölçüm) doğduğu gün aylık partisyonlanır; sonradan partisyonlamanın kendisi başlı başına bir göç projesidir, baştan yapmak neredeyse bedavadır. Aylık otomatik arşiv işi kuruluyor ve izlemeye bağlanıyor. Ağır raporlar da operasyonel veritabanından değil, replika veya rapor katmanından çalıştırılıyor — pazartesi sabahı yönetim raporu çekiliyor diye sahadaki operasyonun yavaşlaması kabul edilebilir bir şey değil.

Bu dördü kurulduğunda "tablo büyüdü, sistem durdu" krizi sizin için tarih oluyor. Kurulmadığında ise kriz bir takvim meselesi; geleceği kesin, tarihi belirsiz.

Mevcut dev tabloyu partisyonlu yapıya taşırken de büyük patlamaya gerek yok: yeni partisyonlu tabloyu yanına kurar, yeni kayıtları oraya akıtır, eskiyi arka planda kontrollü partiler halinde taşırsınız. Trafiğin sakin saatlerinde çalışan bir taşıma işiyle, kullanıcı hiçbir şey hissetmeden birkaç haftada göç tamamlanır. Yavaş ama kesintisiz — bizim tercihimiz hep bu yönde.

Elinizde şu an sınırına dayanmış bir dev tablo varsa, panik yok — yukarıdaki müşteri örneğindeki gibi, çalışan sistemde kesintisiz geçiş mümkün, sadece dikkatli planlama istiyor. Tablonuzun boyutunu, sorgu desenlerinizi ve saklama ihtiyacınızı bize yazın; kaç çekmece gerektiğini birlikte hesaplayalım. Bu hesabı yapmak, ertelemekten her zaman ucuzdur.

📅 Yayınlanma:  ·  Yakup Zengin