Bitemporal Data Nedir? “Ne Zaman Oldu” ve “Ne Zaman Biliyorduk” Sorularını Aynı Anda Cevapla
Bitemporal model ile geçmişe dönük düzeltmeleri kaybetmeden, hem olay zamanı hem kayıt zamanı üzerinden güvenilir raporlama yapın.
Bazı hatalar “yanlış veri” değildir; sadece geç öğrenilmiş doğrudur. Finans, sigorta, envanter veya abonelik gibi alanlarda şu iki soru sürekli karşımıza çıkar:
- Gerçekte ne zaman oldu? (event/effective time)
- Biz bunu ne zaman sisteme kaydettik? (system/recorded time)
Bu iki zaman eksenini birlikte tutan yaklaşıma bitemporal data denir. Tek bir “updated_at” alanı, geçmişe dönük düzeltmelerde hem denetimi hem de doğru raporlamayı bozar.
Problem: “Geriye Dönük Düzeltme” Raporları Neden Bozar?
Örnek: Bir müşterinin abonelik planı 1 Ocak’ta Pro olmuş olsun. Ancak bu değişiklik sistemde 10 Ocak’ta fark edilip girilmiş olsun.
- 5 Ocak’ta “hangi planlar aktifti?” raporunu 6 Ocak’ta çekseydiniz müşteri Basic görünecekti.
- Aynı raporu 12 Ocak’ta çektiğinizde müşteri Pro görünecek.
İki raporun farklı çıkması bazen beklenen şeydir: “O gün bildiğimiz gerçek” ile “bugün bildiğimiz gerçek” farklıdır.
Bitemporal model, ikisini de sorgulanabilir kılar.
Bitemporal Modelin Temel Fikri
Her kayıt için iki aralık tutarsınız:
- Valid Time (Geçerlilik Zamanı): Gerçek dünyada geçerli olduğu aralık
- System Time (Sistem Zamanı): Veritabanında hangi aralıkta “doğru kabul edilip saklandığı”
Pratikte genelde şu alanlarla temsil edilir:
valid_from,valid_tosystem_from,system_to
*_to alanı çoğu zaman “sonsuz” anlamına gelen bir değerle (örn. 9999-12-31) veya NULL ile tutulur.
Küçük Bir Örnek: Abonelik Planı
Tablo: subscription_plan_history
-- Örnek şema (basit)
CREATE TABLE subscription_plan_history (
customer_id BIGINT NOT NULL,
plan TEXT NOT NULL,
valid_from DATE NOT NULL,
valid_to DATE NOT NULL,
system_from TIMESTAMP NOT NULL,
system_to TIMESTAMP NOT NULL,
PRIMARY KEY (customer_id, valid_from, system_from)
);
Senaryo
- Müşteri 1 Ocak itibarıyla Pro’ya geçmiş.
- Biz bu bilgiyi 10 Ocak’ta öğrenip girdik.
İlk giriş (10 Ocak’ta):
INSERT INTO subscription_plan_history
(customer_id, plan, valid_from, valid_to, system_from, system_to)
VALUES
(42, 'PRO', DATE '2026-01-01', DATE '9999-12-31', TIMESTAMP '2026-01-10 09:00:00', TIMESTAMP '9999-12-31 00:00:00');
Sorgu 1: “Gerçekte 5 Ocak’ta hangi plandaydı?”
Bu, valid time sorusu:
SELECT plan
FROM subscription_plan_history
WHERE customer_id = 42
AND DATE '2026-01-05' >= valid_from
AND DATE '2026-01-05' < valid_to
AND TIMESTAMP '2026-01-31 00:00:00' >= system_from
AND TIMESTAMP '2026-01-31 00:00:00' < system_to;
Burada ikinci zaman filtresi “hangi bilgi setiyle bakıyoruz?” sorusunu cevaplar: 31 Ocak’ta bildiğimiz veriye göre.
Sorgu 2: “6 Ocak’ta rapor alsaydım ne görecektim?”
Bu sefer system time’ı 6 Ocak’a çekersiniz:
SELECT plan
FROM subscription_plan_history
WHERE customer_id = 42
AND DATE '2026-01-05' >= valid_from
AND DATE '2026-01-05' < valid_to
AND TIMESTAMP '2026-01-06 12:00:00' >= system_from
AND TIMESTAMP '2026-01-06 12:00:00' < system_to;
10 Ocak’ta girildiği için 6 Ocak “bilgi anında” bu kayıt görünmez. İşte denetim ve raporlama netliği burada gelir.
Düzeltme Nasıl Yapılır? (Kayıt Silmeden)
Bitemporal yaklaşımda “update” çoğu zaman eski kaydı kapat, yenisini aç şeklinde yapılır.
Örn. 15 Ocak’ta öğreniyorsunuz ki Pro geçişi aslında 3 Ocak’ta başlamış.
- Mevcut kaydın
system_to’sunu 15 Ocak yaparsınız (artık sistem açısından “geçersiz”). - Yeni doğru kaydı 15 Ocak sistem zamanı ile eklersiniz.
Bu sayede:
- “Bugün bildiğimiz doğru” değişir.
- “O gün ne biliyorduk?” sorusu bozulmaz.
Ne Zaman Değer? Ne Zaman Fazla?
Değerli olduğu yerler:
- Finansal raporlama ve denetim (audit)
- Faturalama/abonelik geçmişi
- Envanter ve fiyat geçerlilikleri
- Hukuki/regülasyon gerektiren alanlar
Fazla gelebileceği yerler:
- Basit CRUD uygulamaları
- “Son değer yeter” denilen dashboard’lar
Uygulamada 3 İpucu
- Zaman aralıklarını çakıştırmayın: Aynı
customer_idiçin valid aralıkların mantıksal olarak tutarlı olduğundan emin olun. - ‘Sonsuz’ değer standardı belirleyin: NULL mı,
9999-12-31mi? Her yerde aynı olsun. - Sorgu katmanı şart: Bitemporal tabloları ham haliyle her yere açmak yerine, sık kullanılan “as of” sorgularını view veya repository fonksiyonlarıyla standardize edin.
Bitemporal data, “geçmişi düzeltirken geçmişi silmeme” disiplinidir. Özellikle raporların tutarlılığı ve denetim izi önemliyse, updated_at yerine iki zaman ekseniyle düşünmek sisteminize ciddi bir olgunluk katar.