SQL geliştirme ve optimizasyon süreçlerinde, geçici veri depolama ihtiyacı sıkça ortaya çıkar. Bu ihtiyaç, karmaşık sorguların ara sonuçlarını saklamak, veri manipülasyonları yapmak veya kod modülerliğini artırmak için hayati öneme sahiptir. SQL Server’da bu amaçla yaygın olarak kullanılan iki temel mekanizma “Temp Table” (Geçici Tablo) ve “Table Variable” (Tablo Değişkeni) kavramlarıdır. Her ikisi de geçici veri barındırsa da, iç işleyişleri, kullanım alanları ve performans karakteristikleri açısından belirgin farklılıklar gösterirler. Bu makale, her iki yapıyı da detaylı bir şekilde inceleyerek, hangi senaryoda hangisinin tercih edilmesi gerektiğini açıklayacaktır.
Geçici Tablolar (Temp Tables)
Geçici tablolar, adı üzerinde, sadece belirli bir süre boyunca var olan ve genellikle tempdb veritabanında saklanan gerçek tablolardır. SQL Server, geçici tabloları normal tablolar gibi yönetir; bu da onların indekslere, kısıtlamalara (PRIMARY KEY, UNIQUE gibi) ve istatistiklere sahip olabileceği anlamına gelir.
Türleri ve Yaşam Döngüsü
Geçici tablolar iki ana türe ayrılır:
- Yerel Geçici Tablolar (
#TableName): Tek bir kullanıcı oturumuyla sınırlıdır. Tabloyu oluşturan oturum sona erdiğinde veya açıkçaDROP TABLE #TableNamekomutuyla bırakıldığında otomatik olarak silinirler. Farklı oturumlar aynı isimde yerel geçici tablolar oluşturabilir ve bunlar birbirlerinden bağımsızdır. - Genel Geçici Tablolar (
##TableName): Tüm kullanıcı oturumları tarafından erişilebilirler. Tabloyu oluşturan oturum sona erdiğinde ve diğer tüm oturumlar bu tabloya referans vermeyi bıraktığında otomatik olarak silinirler. Adları sunucu genelinde benzersiz olmalıdır.
Özellikleri ve Kullanım Senaryoları
tempdbÜzerinde Depolama: Geçici tablolar fiziksel olaraktempdbveritabanında saklanır. Bu, diske I/O işlemlerine neden olabilir.- İndeksler ve İstatistikler: Geçici tablolara, tıpkı kalıcı tablolarda olduğu gibi kümelenmiş (clustered) ve kümelenmemiş (non-clustered) indeksler eklenebilir. SQL Server sorgu iyileştiricisi (optimizer), bu indeksleri ve otomatik olarak oluşturulan istatistikleri kullanarak sorgu planlarını optimize eder. Bu özellik, büyük veri kümeleriyle çalışırken veya karmaşık birleştirme (JOIN) ve sıralama (ORDER BY) işlemleri gerektiren sorgularda performansı önemli ölçüde artırır.
- İşlem (Transaction) Desteği: Geçici tablolar üzerindeki işlemler geri alınabilir (rollback edilebilir). Bu, veri bütünlüğü açısından kritik durumlarda avantaj sağlar.
- Saklı Yordamlar Arası Erişim: Yerel geçici tablolar, onları oluşturan saklı yordam tarafından oluşturulduktan sonra, bu yordamın çağırdığı diğer saklı yordamlardan da erişilebilir (ancak çağıran yordamın scope’u içinde kalır).
- Büyük Veri Kümeleri: Çok sayıda satır işlenecekse veya bu veriler üzerinde karmaşık operasyonlar (JOIN, GROUP BY, vs.) yapılacaksa geçici tablolar daha iyi bir seçenektir.
Örnek Kullanım
-- Yerel Geçici Tablo Oluşturma
CREATE TABLE #PersonelGecici (
ID INT PRIMARY KEY,
Ad NVARCHAR(50),
Soyad NVARCHAR(50),
DepartmanID INT
);
-- Veri Ekleme
INSERT INTO #PersonelGecici (ID, Ad, Soyad, DepartmanID)
VALUES
(1, 'Ali', 'Can', 101),
(2, 'Ayşe', 'Demir', 102),
(3, 'Mehmet', 'Yılmaz', 101);
-- Sorgulama
SELECT * FROM #PersonelGecici WHERE DepartmanID = 101;
-- İndeks Ekleme (örnek)
CREATE INDEX IX_DepartmanID ON #PersonelGecici (DepartmanID);
-- Tabloyu Silme (oturum sonlandığında otomatik silinir, ancak manuel de silinebilir)
DROP TABLE #PersonelGecici;
Tablo Değişkenleri (Table Variables)
Tablo değişkenleri, bir SQL değişkeni gibi bildirilip kullanılan, ancak TABLE veri tipinde olan özel yapılardır. Genellikle bellekte depolandığı düşünülse de, belirli durumlarda (boyutları büyüdüğünde veya karmaşık işlemler gerektirdiğinde) tempdb‘ye taşınabilirler. Ancak, tempdb‘de depolansalar bile, geçici tablolardan farklı bir mekanizma ile yönetilirler ve daha hafif bir yaklaşıma sahiptirler.
Yaşam Döngüsü
Tablo değişkenlerinin yaşam döngüsü, bildirildiği T-SQL toplu işi (batch), saklı yordam veya fonksiyonla sınırlıdır. Bu kapsamın dışına çıkıldığında veya toplu iş sona erdiğinde, tablo değişkeni otomatik olarak kapsamdan çıkarılır ve bellekten silinir. İşlem (transaction) dışında davranırlar, yani üzerlerindeki değişiklikler geri alınamaz (rollback).
Özellikleri ve Kullanım Senaryoları
- Daha Hafif Kaynak Kullanımı: Geçici tablolara kıyasla daha az kilitlenme (locking) ve günlük kaydı (logging) yükü oluştururlar. Bu, özellikle küçük veri kümeleri üzerinde sık yapılan işlemler için avantajlıdır.
- İstatistik Yokluğu: Tablo değişkenleri için SQL Server istatistik tutmaz. Sorgu iyileştiricisi genellikle tablo değişkeninde yalnızca bir satır olduğunu varsayar. Bu durum, tablo değişkeni büyük miktarda veri içeriyorsa suboptimal (ideal olmayan) sorgu planlarına yol açabilir.
- Sadece Kümelenmiş İndeks (PRIMARY KEY/UNIQUE CONSTRAINT): Tablo değişkenleri üzerinde yalnızca PRIMARY KEY veya UNIQUE CONSTRAINT tanımlanabilir, bu da örtük olarak bir kümelenmiş indeks oluşturur. Kümelenmemiş (non-clustered) indeksler oluşturulamaz.
- Saklı Yordam Yeniden Derlemesi Etkisi Yok: Bir saklı yordam içinde tablo değişkeni kullanılması, yordamın her çalıştırıldığında yeniden derlenmesine neden olmaz. Geçici tablolar ise bazen saklı yordamların yeniden derlenmesine yol açabilir.
- Küçük Veri Kümeleri: Genellikle birkaç yüz veya bin satır gibi nispeten küçük veri kümelerini işlemek için uygundurlar.
Örnek Kullanım
-- Tablo Değişkeni Bildirme
DECLARE @Urunler TABLE (
UrunID INT PRIMARY KEY,
UrunAdi NVARCHAR(100),
Fiyat DECIMAL(10, 2)
);
-- Veri Ekleme
INSERT INTO @Urunler (UrunID, UrunAdi, Fiyat)
VALUES
(101, 'Klavye', 150.00),
(102, 'Fare', 75.50),
(103, 'Monitör', 1200.00);
-- Sorgulama
SELECT * FROM @Urunler WHERE Fiyat > 100.00;
-- Tablo değişkeni, betik (batch) sona erdiğinde otomatik olarak kapsamdan çıkar.
Temp Table vs. Table Variable: Doğru Aracı Seçmek
Hem geçici tablolar hem de tablo değişkenleri, SQL geliştiricilerinin araç kutusundaki değerli enstrümanlardır. Ancak, her birinin kendine özgü güçlü ve zayıf yönleri olduğundan, kullanım senaryosuna göre doğru aracı seçmek performans ve kaynak yönetimi açısından kritik öneme sahiptir.
- Veri Boyutu ve Karmaşıklığı: Eğer işlenecek veri kümesi büyükse (binlerce veya milyonlarca satır) ve üzerinde karmaşık birleştirmeler, filtrelemeler veya sıralamalar yapılacaksa, geçici tablolar genellikle daha iyi bir seçimdir. Çünkü indeksleme ve istatistik mekanizmaları sayesinde sorgu iyileştiricisi daha verimli planlar oluşturabilir. Küçük ve basit veri kümeleri için ise tablo değişkenleri daha az overhead ile hızlı çalışabilir.
- İndeksleme İhtiyacı: Sorgularınızın performansı için kümelenmemiş (non-clustered) indekslere ihtiyaç duyuyorsanız, tek seçeneğiniz geçici tablolardır. Tablo değişkenleri sadece birincil anahtar veya benzersiz kısıtlamalar üzerinden kümelenmiş indeks benzeri bir yapıya izin verir.
- İstatistikler ve Sorgu Planları: SQL Server sorgu iyileştiricisi, geçici tablolar için istatistik tutar ve bunlara dayalı olarak optimum sorgu planları oluşturur. Tablo değişkenleri için istatistik tutulmadığı ve genellikle tek satır varsayımı yapıldığı için, büyük veri kümelerinde geçici tablolar daha performanslı sorgu planları üretebilir.
- İşlem Desteği: Eğer geçici verileriniz üzerindeki değişikliklerin işlem (transaction) kapsamında geri alınabilmesi gerekiyorsa, geçici tabloları tercih etmelisiniz. Tablo değişkenleri işlem kapsamında değildir.
- Saklı Yordam Yeniden Derleme (Recompilation): Çok sık çalıştırılan ve performans kritik saklı yordamlar içinde tablo değişkenleri kullanmak, yordamın yeniden derlenmesini engellediği için daha avantajlı olabilir. Geçici tablolar, şema değişiklikleri nedeniyle bazen yeniden derlemeye yol açabilir.
- tempdb Çekişmesi (Contention): Çok sayıda eş zamanlı işlem
tempdbüzerinde yoğun I/O çekişmesine neden oluyorsa, küçük veri kümeleri için tablo değişkenleri daha hafif bir alternatif sunabilir.
Özetle, SQL’deki geçici tablolar ve tablo değişkenleri, ara veri yönetimi için vazgeçilmez araçlardır. Geçici tablolar, büyük, karmaşık, indeksleme ve işlem desteği gerektiren senaryolar için güçlü bir çözüm sunarken, tablo değişkenleri küçük, basit ve yeniden derleme kaygısının olduğu durumlar için daha hafif ve çevik bir alternatiftir. Doğru seçimi yapmak, veri hacmini, indeksleme ihtiyaçlarını, sorgu optimizasyon beklentilerini ve işlem gereksinimlerini dikkatlice değerlendirerek mümkündür. Her iki yapının da potansiyelini anlamak, daha verimli ve optimize edilmiş SQL kodları yazmanın anahtarıdır.