SQL Server datetime2 ve datetimeoffset: PG’den Geçiş

PostgreSQL’de timestamp saat dilimi saklamaz, timestamptz ise ofseti kaybeder; SQL Server/Azure SQL’de en yakın karşılıklar datetime2 ve datetimeoffset’tur. datetimeoffset hem yerel zamanı hem ofseti birlikte saklar.

PostgreSQL’den SQL Server veya Azure SQL’e geçen geliştiricilerin ilk gün takıldığı konulardan biri, tarih ve saat tiplerinin nasıl davrandığı. Jerry Nixon’ın Azure SQL Dev Corner’da yayımlanan “PostgreSQL to SQL Field Notes” yazısı tam bu noktaya bakıyor: PostgreSQL’deki timestamp ve timestamptz tiplerinin SQL tarafındaki karşılıkları, hangi bilgiyi saklayıp hangisini kaybettikleri, depolama açısından ne anlama geldikleri. Aşağısı, o karşılaştırmanın Türkçe derlenmiş hali.

PostgreSQL’de timestamp: saat dilimi bilgisi yok

PostgreSQL’de timestamp, tarih ve saati saat dilimi bilgisi olmadan saklar. Tipin adı PostgreSQL 7.0 öncesine kadar uzanıyor ama anlamı yolda değişti: 7.0 sürümü eski datetime tipinin yerine timestamp‘i getirdi, 7.2 sürümü de bugün bildiğimiz timestamp without time zone ile timestamp with time zone ayrımını tanımladı. Bugün çıplak bir timestamp yazdığınızda kastedilen timestamp without time zone.

SELECT TIMESTAMP '2026-09-21 10:30:00';

Değer verildiği gibi saklanır; ortada saat dilimi bilgisi yoktur, saklanan da yoktur. Peki değere bir UTC ofseti eklerseniz?

SELECT TIMESTAMP '2026-09-21 10:30:00-06:00';

Bu durumda timestamp ofseti yok sayar, verdiğiniz -06:00 bilgisi atılır. PostgreSQL belgelerinde de bu davranış bugün hala böyle tanımlı. Uygulamanızın orijinal saat dilimini veya ofseti koruması gerekiyorsa bu bilgiyi ayrıca saklamanız gerekir:

CREATE TABLE events (
event_id SERIAL PRIMARY KEY,
event_name TEXT NOT NULL,
event_timestamp TIMESTAMP NOT NULL,
event_timezone TEXT NOT NULL
);

Çalışır, ama artık tek bir olayı iki ayrı sütun tarif ediyor. İki değerin birlikte taşınması ve doğru yorumlanması da tamamen uygulamanın sorumluluğuna kalıyor.

SQL tarafındaki en yakın karşılık: datetime2

PostgreSQL timestamp tipinin SQL’deki en yakın karşılığı datetime2. SQL Server’ın eski datetime tipinin modern yerine geçen seçeneği bu; Microsoft yeni geliştirmeler için datetime2 kullanılmasını öneriyor.

Dikkat çeken fark hassasiyette. datetime2, 0 ile 7 basamak arasında değişken kesirli saniye hassasiyeti destekliyor ve varsayılan olarak datetime2(7) ile geliyor, yani varsayılan ayarda zamanı 100 ns adımlarıyla temsil edebiliyor. PostgreSQL’deki timestamp ise 6 kesirli saniye basamağı, yani 1 μs adımı destekliyor. SQL Server tarafı bu haliyle 10 kat daha ince bir temsil sunuyor.

Bilimsel cihaz verisi, akış (streaming) verisi veya finansal uygulamalar gibi yüksek hassasiyet isteyen senaryolarda datetime2 bu konuda ödün vermenizi gerektirmiyor.

timestamptz ne yapar, ne yapmaz

PostgreSQL’in timestamptz kısaltmasıyla yazılan timestamp with time zone tipinde ofset önemsenir:

SELECT TIMESTAMPTZ '2026-09-21 10:30:00-06:00';

Burada PostgreSQL ofseti kullanarak gerçek zaman anını belirler, bu anı dahili olarak UTC biçiminde saklar. Orijinal saat dilimini veya ofseti ise saklamaz; değer okunurken oturumun geçerli TimeZone ayarına göre dönüştürülür.

Yani “uygulama başlangıçta hangi ofseti gönderdi?” sorusunun cevabı PostgreSQL’de yok. Üstelik oturumun TimeZone ayarı da kullanıcının ya da uygulamanın yerel saat dilimini kendiliğinden bilmez; onu uygun şekilde ayarlamak veya dönüşümü kendi yapmak uygulamanın işi. Aynı saklanan değer bu yüzden kimin sorduğuna göre farklı görünebilir:

SET TIME ZONE 'America/Denver';
SELECT TIMESTAMPTZ '2026-09-21 10:30:00-06:00';
-- 2026-09-21 10:30:00-06
SET TIME ZONE 'America/New_York';
SELECT TIMESTAMPTZ '2026-09-21 10:30:00-06:00';
-- 2026-09-21 12:30:00-04

İki sonuç da tam olarak aynı zaman anını temsil eder, PostgreSQL’in bilinçli davranışıdır bu. Fakat uygulamanız orijinal değerin 10:30 -06:00 olduğunu bilmek zorundaysa timestamptz bunu söyleyemez, o bilgi ekleme sırasında kaybolur. Orijinal ofsete ihtiyaç duyan geliştiriciler bilgiyi değerin içine gömmek yerine ayrıca saklamak zorunda kalıyor. timestamptz‘ın kazandırdığı şey ise zaman damgalarını ortak bir ana normalleştirmesi, okuma sırasında da oturumun yapılandırılmış saat dilimine otomatik çevirmesi.

datetimeoffset: yerel zaman ve ofset birlikte

SQL tarafında saat dilimi bilgisi önemliyse devreye datetimeoffset giriyor. Bu tip hem yerel tarih ve saati hem de UTC’den ofseti saklıyor, zaman damgasının orijinal bağlamı böylece korunuyor.

DECLARE @dt DATETIMEOFFSET = '2026-09-21 10:30:00-06:00';

Tip SQL Server 2008’den beri var ve modern SQL Server uygulamalarında yaygın olarak kullanılıyor. '2026-09-21 10:30:00-06:00' gibi bir değer eklediğinizde SQL Server -06:00 ofsetini tarih ve saatle birlikte saklar.

Değeri UTC olarak göstermek isterseniz iki basit yol var:

SELECT @dt AT TIME ZONE 'UTC';
SELECT SWITCHOFFSET(@dt, '+00:00');

İkisi de aynı anı UTC olarak döndürür. AT TIME ZONE, adlandırılmış saat dilimleri ve bunların dönüşüm kurallarıyla çalışırken işe yarıyor. Elinizde zaten bir datetimeoffset varsa ve yalnızca gösterilen ofseti UTC’ye çevirmek istiyorsanız SWITCHOFFSET daha basit kalıyor.

datetime2 ile gelen yüksek hassasiyet datetimeoffset için de geçerli, üstüne saat dilimi farkındalığı ekleniyor:

-- Example showing high precision with datetimeoffset
DECLARE @dtHighPrecision DATETIMEOFFSET(7) = '2026-09-21 10:30:00.1234567-06:00';
SELECT @dtHighPrecision;

Depolama farkı ve varsayılan tip seçimi

datetimeoffset, kesirli saniye hassasiyetine bağlı olarak 8 ila 10 bayt yer kaplıyor. 6 ila 8 bayt gerektiren datetime2‘ye göre biraz daha fazla; fazladan 2 bayt saat dilimi ofsetini saklıyor.

Satır datetimeoffset datetime2
1 milyar 8–10 GB 6–8 GB

Bir milyar satırda fark 2 GB. Tarih alanları çoğu uygulamada bol bol kullanıldığından bu fark, toplam depolama ihtiyacında ve performansta hissedilir bir etki yaratabiliyor. Kazanç sadece diskte de olmuyor; G/Ç yükü, bellek baskısı ve dizin boyutu da aşağı inebiliyor.

Bu nedenle varsayılan tercihiniz her zaman datetimeoffset olmak zorunda değil. Uygulamanız saat dilimiyle ilgilenmiyorsa datetime2 pek çok senaryoda mükemmel bir seçim olmayı sürdürüyor. Hassasiyet değişken olduğu için, saat dilimi farkındalığına ihtiyaç duyduğunuz durumlarda bile uygun hassasiyeti seçip depolama ile ihtiyaç arasında denge kurabilirsiniz:

Satır datetimeoffset(0) datetimeoffset(7)
1 milyar 8 GB 10 GB

En düşük ve en yüksek hassasiyet arasında bir milyar satırda yine 2 GB’lık bir fark oluşuyor, üstelik saat dilimi desteğinden vazgeçmeden.

Geçiş yaparken akılda tutulacaklar

Kaynak yazının özeti kabaca şöyle toparlanabilir: PostgreSQL’den geçiş gerçek bir iş yükü ve eski PostgreSQL sürümünüze bağlı olarak karmaşıklığı ciddi biçimde değişebiliyor. SQL standardı iki motorun şeklini büyük ölçüde hizaladığı için bu tanıdıklık hızlı ilerlemenize yardımcı oluyor, yine de her şeyin birebir karşılığı bulunmuyor. Tarih ve saat tarafında pratik karşılık tablosu şöyle:

  • timestamp (saat dilimsiz) → datetime2, daha ince hassasiyetle.
  • timestamptz → datetimeoffset, ancak orijinal ofseti kaybetmeden.
  • Saat dilimi önemli değilse datetime2 ile depolamadan kazanç sağlayın.

Uygulamanız için doğru tarih ve saat tipini seçmek önemli bir karar; SQL tarafında bu kararı vermek için gereken seçenekler tip düzeyinde hazır geliyor.

Kaynaklar ve İleri Okuma

Bu yazı yapay zeka (büyük dil modelleri) ile hazırlanmış, insan editör tarafından incelenmiştir. İçerik üretim sürecimiz.
Aşkın KILIÇ

20+ yıl deneyimli Azure Solutions Architect. Microsoft sertifikalı bulut mimari ve DevOps danışmanı. Azure, yapay zekâ ve bulut teknolojileri üzerine Türkçe teknik içerikler üretiyor.

AZ-305AZ-104AZ-500AZ-400DP-203AI-102

Bu içerik işinize yaradı mı?

Benzer içerikleri kaçırmamak için YouTube ve GitHub hesaplarımı takip edin.

Haftalık Bülten

Her pazar özenle seçilmiş teknoloji yazıları doğrudan e-postanıza gelsin.

2 Yorum

  1. Biz de geçen sene PG’den Azure SQL’e geçtik ve timestamptz’nin ofseti kaybettiğini ancak o zaman fark ettim. datetimeoffset bu konuda gerçekten hayat kurtarıyor, keşke bu yazıyı o dönem okusaymışım. Peki indeksleme tarafında datetime2 ile datetimeoffset arasında performans farkı gözlemlediniz mi?

  2. Biz de geçen sene PG’den Azure SQL’e geçmiştik, timestamptz’nin ofseti kaybetmesi yüzünden epey uğraşmıştık. datetimeoffset’in hem yerel zamanı hem ofseti tutması gerçekten büyük avantaj, keşke o zaman bu yazıyı okusaydım. Peki indeksleme tarafında datetime2 ile datetimeoffset arasında ciddi performans farkı gördünüz mü?

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

✉

Haftalık Bülten

Azure, DevOps ve Yapay Zeka dünyasındaki en güncel içerikleri her hafta doğrudan e-postanıza alın.

Spam yok. İstediğiniz zaman iptal edebilirsiniz.
📱
Uygulamayı Yükle Ana ekrana ekle, çevrimdışı oku
Kategoriler
Ara
Paylaş
WhatsApp
İçindekiler
← Azure Synapse: Silinen Workspa...
Kubernetes PVC Unused Conditio... →
📩

Gitmeden önce!

Her pazar özenle seçilmiş teknoloji yazıları ve AI haberleri doğrudan e-postanıza gelsin. Ücretsiz, spam yok.

🔒 Bilgileriniz güvende. İstediğiniz zaman ayrılabilirsiniz.

📬 Haftalık bülten: Teknoloji + AI haberleri
Beni Takip Et Yeni Azure / AI / DevOps yazılarını GitHub ve RSS üzerinden takip edin.