- Verinin belirli bir tarihteki (geçen salı) halinin ne olduğunu soran sorgulara yanıt verebilmek için Postgres 19, yerel zamansal geçmiş tablosu (temporal table) desteği getiriyor; böylece ayrı bir denetim tetikleyicisi sistemi olmadan değişiklik öncesi ve sonrası veriler izlenebiliyor
- SQL:2011 standardının 10 yılı aşkın süre önce tanımladığı Temporal tablolar, Postgres tarafından ancak şimdi çekirdeğe alınıyor; böylece diğer veritabanı motorlarına kıyasla daha geç katılmış oluyor
- Mevcut
valid_from/valid_toiki sütunu vebtree_gistuzantısı tabanlı dışlama kısıtı (exclusion constraint) yerine, tek bir aralık türü (range type) sütunu veWITHOUT OVERLAPSkısıtıyla daha sezgisel bir ifade sunuluyor FOR PORTION OFsözdizimiyle UPDATE·DELETE sırasında satırlar otomatik bölünüyor, zaman eksenindeki boşluk ve çakışmalar motor tarafından ele alınıyor- Bu ekleme, iki zamanlı (bi-temporal) sistemlerin yalnızca geçerlilik zamanı (application time) yarısını kapsıyor; sistem zamanı (system time) henüz desteklenmese de ilerideki sürümler için temel atıyor
Mevcut yöntem - The Old-Fashioned Way
- Ürün fiyatlarını zaman içinde izlemeye yönelik ilk yaklaşım,
valid_from,valid_toadlı iki tarih sütunu vevalid_from < valid_toCHECK kısıtından oluşuyordu- Ancak aynı ürün için tarih aralığı çakışan iki satırın eklenmesini engelleyemiyordu (ör. ürün 42 aynı salı günü hem $9.99 hem de $14.99)
- Geleneksel çözüm,
btree_gistuzantısı ve dışlama kısıtı (exclusion constraint) kullanmaktıEXCLUDE USING gist (product_id WITH =, daterange(valid_from, valid_to) WITH &&)biçimiyle çakışan satır eklenince hata veriliyordu
- Bu yaklaşımın sorunları
- GiST, Postgres'e özgü bir indeksleme yapısı olduğundan deneyim gerektiriyor ve isteğe bağlı bir uzantı olması giriş bariyeri yaratıyor
- Dışlama kısıtı sözdizimi sezgisel değil; standart bir yaklaşım olarak akla gelmesi zor
- Tabloya zaman farkındalığı gömülü değil; zaman aralıkları değiştiğinde satırları elle bölmek ve birleştirmek gerekiyor, zamansal tutarlılık yükü uygulamaya aktarılıyor
Zamanın kısa tarihi - A Brief History of Time
- SQL:2011 standardı, geçerlilik zamanı dönemini (
APPLICATION TIME),WITHOUT OVERLAPSkısıtını ve zamansal veri işleme içinFOR PORTION OFsözdizimini tanımladı - Henrietta Dombrovskaya (Hetti), Chad Slaughter ile birlikte pg_bitemporal uzantısını geliştirdi; bu, Postgres içinde PL/pgSQL ile iki zamanlı tabloları yöneten bir çerçeve
- 2015'ten bu yana çeşitli konferanslarda kavramı anlattı; **geçerlilik zamanı (valid time)**nı (gerçek dünyada bir bilginin doğru olduğu an) ve **işlem zamanı (transaction time)**nı (veritabanının bu bilgiyi kaydettiği an) aynı anda izlemeyi gösterdi
- İki zaman boyutunun farkı
- Geçerlilik zamanı, "bu fiyat ocaktan hazirana kadar geçerli" anlamına geliyor
- İşlem zamanı ise veritabanı açısından "bu satır 12 Mart saat 15:47'de eklendi, 3 Nisan saat 09:01'de değiştirildi" demek
- İkisi birleştirildiğinde, "o zaman bildiğimiz bilgiye göre geçen salı fiyatın ne olduğunu düşünüyorduk" sorusuna yanıt veren iki zamanlı tablolar kurulabiliyor
- pg_bitemporal,
EXCLUDE USING gistifadesini iki kez kullanıyor; birieffectivearalığına (geçerlilik zamanı), diğeriassertedaralığına (işlem zamanı) uygulanıyor- İki zamanlı ekleme, güncelleme, düzeltme, devre dışı bırakma ve silme işlevleri ile zamansal çıkarım için Allen'ın aralık ilişkileri (Allen's interval relationships) desteği sunuyor
- Uzantının sınırları
- Sorgu planlayıcısını zamansal koşulları tanıyacak şekilde değiştiremiyor, motor düzeyindeki kısıt sistemiyle bütünleşemiyor, yerel veri işleme sözdizimi sağlayamıyor → çekirdeğe girmesi gerekiyordu
- Postgres 19, iki zamanlı sistemlerin geçerlilik zamanı yarısını benimsiyor; tam çözüm değil ama büyük bir ilerleme
Aralıklar imdada yetişiyor - Ranges to the Rescue
- Postgres 19 yaklaşımı, ayrı
valid_from/valid_toyerine tek bir aralık türü sütunu olanvalid_at DATERANGEkullanıyorPRIMARY KEY (product_id, valid_at WITHOUT OVERLAPS)ilebtree_gistuzantısı ve dışlama kısıtı gerekmiyorWITHOUT OVERLAPS,product_iddeğerinin herhangi bir anda benzersiz olmasını sağlıyor; ama aralıklar çakışmadığı sürece aynı ürün için birden fazla satıra izin veriyor
- İçeride hâlâ GiST indeksi kullanılıyor ve anahtarın zamansal olmayan sütunları için
btree_gistgerekiyor; ancak kısıt oluşturulurken bağımlılıklar Postgres tarafından otomatik yönetiliyor - Aralık gösteriminde
[dahil,)hariç anlamına geliyor →[2025-01-01, 2025-07-01)1 Ocak'ı kapsıyor, 1 Temmuz'u kapsamıyor- Son Gadget satırı
[2026-01-01,), bitiş tarihi olmayan açık uçlu (open-ended) bir aralık; yani mevcut fiyat için tanımlı bir bitiş yok
- Son Gadget satırı
- Çakışma korumasının davranışı
- Hatalı
[2025-03-01, 2025-01-01)aralığı eklenirse "aralığın alt sınırı üst sınırdan küçük veya ona eşit olmalı" hatası veriliyor - Çakışan
[2025-03-01, 2025-09-01)aralığı eklenirseproducts_pkeydışlama kısıtı ihlali oluşuyor - Yalnızca aralık türü kullanarak iki tür doğrulama birden elde ediliyor
- Hatalı
Kesip biçmek - Slicing and Dicing
- Bir ürünün fiyatını yalnızca 2025 Mart–Eylül arasında $10.99 yapmak istenirse, eski yöntemde satırları elle bölmek ve eklemek gerekiyordu; bu da hata halinde boşluk ve çakışmalar doğurabiliyordu
- Zamansal geçmiş tablosunda bu, niyet edildiği gibi doğrudan ifade edilebiliyor
UPDATE products FOR PORTION OF valid_at FROM '2025-03-01' TO '2025-09-01' SET price = 10.99 WHERE product_id = 1
- Sonuç olarak Widget satırları 3'ten 5'e çıkıyor
- Mevcut $9.99 satırı
[2025-01-01, 2025-03-01)aralığına küçülüyor - Kalan aralık için yeni bir $10.99 satırı ekleniyor
- Mevcut $12.99 satırı
[2025-09-01, 2026-01-01)aralığına küçülüyor - Kalan
[2025-07-01, 2025-09-01)aralığı için yeni bir $10.99 satırı daha ekleniyor
- Mevcut $9.99 satırı
- $10.99'ın iki satıra bölünmesinin nedeni,
FOR PORTION OFifadesinin eşleşen her satırı bağımsız işlemesi ve bitişik aralıkları sonradan birleştirmemesi (coalesce)- Nihai sonuçta boşluk ya da çakışma yok; bu da salt dışlama mantığının (exclusion logic) sunmadığı bir avantaj
- Sınır durumlar (edge case)
FOR PORTION OFaralığı mevcut tek bir satırın tamamen içindeyse, en fazla 2 artık satır (ön ve arka) oluşabiliyor- Mevcut sınırlarla tam çakışıyorsa artık satır gerekmiyor
- Yeni oluşan zamansal artık satırlar için
INSERTizni gerekmiyor, ancak mevcutINSERTtetikleyicileri yine çalışıyor → denetim kaydı veyaSECURITY DEFINERtetikleyici işlevlerinde buna dikkat etmek gerekiyor
Geçmişi silmek - Erasing History
FOR PORTION OF,DELETEiçin de çalışıyor; örneğin belirli bir ürünü 2025 Haziran–Ekim arasında katalogdan geçici olarak kaldırmak mümkünDELETE FROM products FOR PORTION OF valid_at FROM '2025-06-01' TO '2025-10-01' WHERE product_id = 2
- Sonuç
- Haziran–Ekim aralığı kesilip çıkarılıyor ve
[2025-04-01, 2026-01-01)aralığını kaplayan $22.99 satırı, haziranda biten bir satır ile ekimde başlayan iki artık satıra bölünüyor - Boşluğun öncesi ve sonrasındaki fiyat verisi özgün değerleriyle korunuyor; yani DELETE, satır sayısını artırabiliyor
- Haziran–Ekim aralığı kesilip çıkarılıyor ve
- Zamansal geçmiş tablosu yönetim mekanizması bunların hepsini otomatik yapıyor; böylece uygulama düzeyinde aşırı silme veya sahipsiz parça (orphaned fragment) riski ortadan kalkıyor
Reklamdaki doğruluk - Truth in Advertising
- Zamansal geçmiş tabloları, zamansal dış anahtarlar (temporal foreign key) olmadan tamamlanmış sayılmaz; Postgres 19 bunu
PERIODanahtar sözcüğüyle destekliyorFOREIGN KEY (product_id, PERIOD valid_at) REFERENCES products (product_id, PERIOD valid_at)biçiminde tanımlanıyor
PERIODanahtar sözcüğü, dış anahtarın kendisinin zamansal tabanlı olduğunu belirtiyor- Başvurulan product kaydı, variant'ın
valid_ataralığının tamamı boyunca mevcut olmalı - Başvurulan tablodaki tüm eşleşen satırların birleşimi, başvuran satırın zaman aralığını tamamen kapsamalı
- Başvurulan product kaydı, variant'ın
- product zaman aralığını aşan bir variant oluşturma girişimi (
[2025-01-01, 2027-01-01)) reddediliyor- Widget fiyatı yalnızca 2026 ortasına kadar tanımlıyken 2027'ye kadar geçerli olduğunu iddia eden bir variant, dış anahtar kısıtı ihlaliyle engelleniyor
- Önemli bir sınırlama var
- Zamansal dış anahtarlar, başvuru eylemi (referential action) olarak yalnızca
NO ACTIONdestekliyor;CASCADE,SET NULLveSET DEFAULTyok - Variant'ın bağlı olduğu product satırı silinirse her zaman hata oluşuyor; bunun nedeni zincirleme zamansal işlemlerin karmaşıklığı ve bunun uygulama tarafından açıkça ele alınması gereği
- Zamansal dış anahtarlar, başvuru eylemi (referential action) olarak yalnızca
Küçük adımlar - Baby Steps
- Şu anda gelen yetenekler: çakışmayı önleyen geçerlilik zamanı tabanlı zamansal geçmiş tabloları, zamansal veri işleme ve zamansal dış anahtarlar
- En büyük eksik, işlem zamanı olarak da bilinen sistem zamanı (system time)
- Geçerlilik zamanı, bir olgunun gerçek dünyada ne zaman doğru olduğunu izler; sistem zamanı ise veritabanının bu olgudan ne zaman haberdar olduğunu izler; birçok sistem her ikisini de kullanır
- Bu alanı 2015'ten beri pg_bitemporal uzantısı dolduruyordu
- Tetikleyicilerle sistem zamanını taklit etmek mümkün, ancak bu; diğer yeni zamansal özelliklerde olduğu gibi motorun şeffaf biçimde yönetmesiyle aynı şey değil
- Zamansal geçmiş tablosu belgeleri de sistem zamanının yerel olarak desteklenmediğini, ama taklit edilebildiğini açıkça belirtiyor; Postgres 20 ve sonrası için eklenip eklenmeyeceği belirsiz olsa da temel şimdiden atılmış durumda
Son düşünceler - Final Thoughts
EXCLUDE USING gistyaklaşımı çalışıyor ama görece kaba bir geçici çözüm; pg_bitemporal gibi uzantılar kavramı kanıtlayıp tartışmayı bugüne taşıdı- GiST dışlama kısıtlarına göre çok daha sezgisel bir yaklaşım
- Birincil anahtardaki
WITHOUT OVERLAPSsıradan bir İngilizce ifade gibi okunuyor,FOR PORTION OFise yaptığı işi doğrudan anlatıyor - Zamansal güncelleme ve silmelerde otomatik satır bölme, potansiyel hata sınıflarından birini ortadan kaldırıyor
- Birincil anahtardaki
- SQL:2011'den Postgres 19'a uzanan yol uzun oldu; Hetti ve topluluk yıllar boyunca bu desenin gerekliliğini ve uygulanabilirliğini gösterdi, şimdi de çekirdeğe girmiş oldu
- Gelecek sürümlerde sistem zamanı desteğini izlemek gerekecek; Postgres iki zamanlı yapının her iki yarısını da tamamladığında olasılıklar ciddi biçimde genişleyecek
Henüz yorum yok.