Merhabalar,
Bu yazıda SQL Server’da sorgu performansının en kritik kavramlarından biri olan SARGable üzerine konuşacağız. SARGable’ın ne olduğunu, neden bu kadar önemli olduğunu ve sorgularımızı nasıl SARGable hale getirebileceğimizi detaylı örneklerle inceleyeceğiz.
SARGable Nedir?
SARGable, “Search ARGument ABLE” kelimelerinin kısaltmasıdır. Türkçeye “arama argümanına uygun” olarak çevrilebilir. Bir sorgunun SARGable olması, SQL Server’ın index (dizin) yapılarını verimli bir şekilde kullanarak verilere erişebilmesi anlamına gelir.
Yazılım geliştirirken performans optimizasyonu kavramını sıkça duymuşuzdur. Veritabanı tarafında bu optimizasyonun en temel yapı taşlarından biri index kullanımıdır. Ancak bir tabloya index eklemek tek başına yeterli değildir. Yazdığımız sorguların bu index’leri kullanabilecek şekilde yazılmış olması gerekir. İşte SARGable tam olarak bu noktada devreye girer.
Bunu gerçek hayattan bir örnekle açıklayalım. Bir kütüphaneye gittiğinizi ve “Fyodor Dostoyevski” yazarına ait kitapları aradığınızı düşünün. Kütüphanecinin iki seçeneği vardır:
- Katalog Kullanmak (SARGable): Yazar kataloğuna bakıp doğrudan “Dostoyevski” bölümüne gitmek
- Tüm Kitapları Taramak (Non-SARGable): Kütüphanedeki tüm kitapları tek tek eline alıp yazarına bakmak
Hangisi daha hızlı? Tabii ki katalog kullanmak. İşte SQL Server’daki index de bu katalog gibi çalışır. SARGable sorgular index’i kullanarak doğrudan hedef veriye ulaşırken, non-SARGable sorgular tüm tabloyu taramak zorunda kalır.
Index Kavramına Kısa Bir Bakış
SARGable kavramını tam olarak anlayabilmek için önce index’in nasıl çalıştığını bilmemiz gerekir. SQL Server’da en yaygın kullanılan index türü B-Tree (Balanced Tree) yapısındadır. Bu yapı, verileri sıralı bir şekilde tutar ve arama işlemlerini logaritmik zamanda gerçekleştirir.
Bir tabloda 1.000.000 (bir milyon) satır olduğunu düşünelim. Index olmadan bir veri aramak, en kötü durumda 1.000.000 satırı tek tek kontrol etmek demektir. Ancak B-Tree index ile bu sayı yaklaşık 20 karşılaştırmaya düşer. Bu dramatik fark, index kullanımının neden bu kadar kritik olduğunu açıkça gösterir.
Ancak burada önemli bir nokta var: Index’in var olması, SQL Server’ın onu kullanacağı anlamına gelmez. Sorgunun yazılış şekli, index kullanımını doğrudan etkiler. İşte SARGable kavramının önemi tam olarak burada ortaya çıkar. Indexle alakalı daha detaylı bilgiye buradan erişebilirsiniz.
SARGable ve Non-SARGable Farkı
SQL Server, bir sorguyu çalıştırmadan önce Query Optimizer adı verilen bir bileşen aracılığıyla sorguyu analiz eder. Bu analiz sırasında, mevcut index’lerin kullanılıp kullanılamayacağına karar verir.
- SARGable Sorgu: Query Optimizer index kullanabilir. Sonuç: Index Seek (hızlı, verimli)
- Non-SARGable Sorgu: Query Optimizer index kullanamaz. Sonuç: Index Scan veya Table Scan (yavaş, verimsiz)
Index Seek ve Index Scan arasındaki fark çok önemlidir:
- Index Seek: Doğrudan hedef veriye gider. Sadece ihtiyaç duyulan satırları okur.
- Index Scan: Tüm index’i baştan sona tarar. Milyonlarca satırı okumak zorunda kalabilir.
Senaryo: E-Ticaret Sipariş Sistemi
Bir e-ticaret platformu geliştirdiğimizi ve sipariş takibi için aşağıdaki tabloya sahip olduğumuzu varsayalım:
-- Orders tablosu: 10 milyon sipariş kaydı içeriyor
CREATE TABLE Orders
(
OrderId INT IDENTITY(1,1) PRIMARY KEY,
CustomerId INT NOT NULL,
OrderDate DATETIME NOT NULL,
TotalAmount DECIMAL(18,2) NOT NULL,
Status NVARCHAR(50) NOT NULL,
ShippingCity NVARCHAR(100) NULL
);
Bu tabloda 10 milyon sipariş kaydı bulunuyor ve OrderDate sütununda bir index mevcut. Şimdi farklı sorguların nasıl davrandığını inceleyelim.
Örnek 1: Tarih Karşılaştırmaları
Tarih sütunları, SARGability açısından en çok hata yapılan alanlardan biridir. Aynı sonucu veren iki farklı sorguyu karşılaştıralım.
Non-SARGable Sorgu (Kötü Yaklaşım):
-- 2024 yılındaki siparişleri getir
SELECT OrderId, CustomerId, TotalAmount
FROM Orders
WHERE YEAR(OrderDate) = 2024;
Bu sorgu neden non-SARGable? Çünkü YEAR() fonksiyonu, OrderDate sütunundaki her bir değeri alıp yılını hesaplamak zorundadır. SQL Server, index içinde “2024 yılı” diye bir değer aramaz; index tam tarih değerlerini tutar. Bu nedenle Query Optimizer, index’i kullanamaz ve tüm tabloyu taramak zorunda kalır.
SARGable Sorgu (İyi Yaklaşım):
-- 2024 yılındaki siparişleri getir
SELECT OrderId, CustomerId, TotalAmount
FROM Orders
WHERE OrderDate >= '2024-01-01' AND OrderDate < '2025-01-01';
Bu sorgu SARGable’dır. SQL Server, index içinde 2024-01-01 ile 2025-01-01 arasındaki değerleri doğrudan bulabilir. Herhangi bir hesaplama yapmak zorunda değildir.
Örnek 2: String Aramaları ve LIKE Operatörü
String sütunlarında arama yaparken LIKE operatörünün kullanım şekli SARGability’yi doğrudan etkiler.
SARGable Sorgu (Başlangıç Araması):
-- "Ist" ile başlayan şehirlerdeki siparişler
SELECT OrderId, CustomerId, ShippingCity
FROM Orders
WHERE ShippingCity LIKE 'Ist%';
Bu sorgu SARGable’dır. Neden? Çünkü index, değerleri alfabetik sıraya göre tutar. “Ist” ile başlayan tüm değerler index içinde yan yana konumlanır. SQL Server, doğrudan bu bölgeye gidip arama yapabilir.
Non-SARGable Sorgu (Bitiş Araması):
-- "bul" ile biten şehirlerdeki siparişler
SELECT OrderId, CustomerId, ShippingCity
FROM Orders
WHERE ShippingCity LIKE '%bul';
Bu sorgu non-SARGable’dır. Index değerleri başlangıç karakterine göre sıralıdır, bitiş karakterine göre değil. SQL Server, tüm index’i taramak zorundadır.
Örnek 3: Fonksiyon Kullanımı
Sütunlara fonksiyon uygulamak, SARGability’nin en büyük düşmanıdır. Bu durum sadece tarih fonksiyonlarıyla sınırlı değildir.
Non-SARGable Örnekler:
-- UPPER fonksiyonu
WHERE UPPER(ShippingCity) = 'ISTANBUL';
-- SUBSTRING fonksiyonu
WHERE SUBSTRING(ShippingCity, 1, 3) = 'Ist';
-- CONVERT fonksiyonu
WHERE CONVERT(VARCHAR(10), OrderDate, 112) = '20240315';
Bu sorguların hepsi non-SARGable’dır. Her birinde SQL Server, ilgili sütundaki her değeri fonksiyondan geçirmek zorundadır.
Örnek 4: Matematiksel İşlemler
Sütunlar üzerinde matematiksel işlem yapmak da SARGability’yi bozar.
Non-SARGable Sorgu:
SELECT DISTINCT CustomerId
FROM Orders
WHERE TotalAmount * 12 > 120000;
SARGable Alternatif:
-- Matematiksel işlemi değer tarafına taşı
SELECT DISTINCT CustomerId
FROM Orders
WHERE TotalAmount > 10000; -- 120000 / 12 = 10000
Aynı mantıksal sonucu veren bu sorgu SARGable’dır. Hesaplamayı sorgu yazarken siz yapıyorsunuz, SQL Server’a yaptırmıyorsunuz.
Performans Karşılaştırması
10 milyon kayıt içeren Orders tablomuzda, son 30 gündeki siparişleri listeleyen iki farklı sorgunun performans karşılaştırması:
| Metrik | Non-SARGable | SARGable | Fark |
| Execution Time | ~12 saniye | ~150 ms | ~80x |
| Logical Reads | 45.230 sayfa | 1.245 sayfa | ~36x |
| Scan Type | Index Scan | Index Seek | ✓ |
SARGable Sorgu Yazımı İçin Altın Kurallar
İncelediğimiz örneklerden çıkarabileceğimiz temel kuralları özetleyelim:
1. WHERE Koşulundaki Sütunlara Fonksiyon Uygulamayın
YEAR(), MONTH(), UPPER(), LOWER(), SUBSTRING(), CONVERT(), CAST(), ISNULL() gibi fonksiyonlar index kullanımını engeller. Fonksiyonu değer tarafına taşıyın veya alternatif yaklaşımlar kullanın.
2. LIKE Kullanırken Joker Karakteri Başa Koymayın
LIKE ‘abc%’ SARGable, LIKE ‘%abc’ non-SARGable’dır. Ortada arama (‘%abc%’) en kötü senaryodur.
3. Matematiksel İşlemleri Sütun Yerine Değer Tarafında Yapın
WHERE Salary > 10000 yazın, WHERE Salary * 12 > 120000 yazmayın. Hesaplamayı sorgu dışında yapın.
4. Doğru Veri Tiplerini Kullanın
INT sütunu INT ile, NVARCHAR sütunu NVARCHAR ile karşılaştırın. Örtük dönüşümlerden kaçının.
5. Tarih Karşılaştırmalarında Aralık Kullanın
WHERE YEAR(OrderDate) = 2024 yerine WHERE OrderDate >= ‘2024-01-01’ AND OrderDate < ‘2025-01-01’ yazın.
6. NULL Kontrollerinde IS NULL/IS NOT NULL Kullanın
WHERE ISNULL(Column, ‘default’) = ‘default’ yerine WHERE Column IS NULL yazın.
Sonuç
Bu yazımızda, SQL Server sorgu performansının kritik kavramlarından biri olan SARGable’ı inceledik. SARGable’ın “Search ARGument ABLE” kelimelerinin kısaltması olduğunu ve bir sorgunun index yapılarını verimli şekilde kullanabilmesi anlamına geldiğini gördük.
Tarih fonksiyonları, string manipülasyonları, matematiksel işlemler ve veri tipi uyumsuzlukları gibi yaygın senaryolar üzerinden, non-SARGable sorguların nasıl ortaya çıktığını ve bunları SARGable hale getirmek için hangi tekniklerin kullanılabileceğini örneklerle inceledik.
SARGable sorgu yazmanın temel prensibi aslında çok basittir: WHERE koşulundaki sütunu olduğu gibi bırakın, tüm işlemleri değer tarafında yapın. Bu basit kuralı uyguladığınızda, sorgularınızın büyük çoğunluğu otomatik olarak SARGable olacaktır.
Küçük tablolarda SARGable ve non-SARGable sorgular arasındaki fark belki milisaniyeler düzeyinde kalır. Ancak tablolar büyüdükçe, bu fark saniyelerden dakikalara, hatta saatlere çıkabilir. Bir e-ticaret sitesinde sipariş listeleyen sorgunun 12 saniye yerine 150 milisaniyede çalışması, kullanıcı deneyimi açısından hayati önem taşır.
SARGable kavramını anlamak ve uygulamak, sadece veritabanı yöneticilerinin değil, veritabanıyla çalışan her yazılım geliştiricinin sahip olması gereken temel becerilerden biridir.
Bu yazıda SQL Server’da SARGable kavramını inceledik, bir sonraki yazılarda görüşmek üzere.
İyi çalışmalar.