SQL Server'da Cardinality Estimator (CE), sorgu optimizasyonunun kalbinde yer alan, istatistiksel bir tahmin motorudur. Temel işlevi, bir sorgunun yürütülmesi sırasında her işlemin (operation) çıktısından beklenen satır sayısını, yani cardinality'yi tahmin etmektir. Bu tahminler, Query Optimizer'ın maliyet tabanlı karar alma sürecinin en kritik girdisidir.
Tahmin işlemi, tablo ve indeks istatistikleri, veri dağılımı, sorgu yüklemleri (predicates) ve operatörler (JOIN, FILTER, GROUP BY) gibi faktörlerin karmaşık bir kombinasyonuna dayanır. CE'nin hesapladığı beklenen satır sayısı, Optimizer'a farklı yürütme planlarının göreli maliyetlerini hesaplama imkanı verir. Bir JOIN işleminin birkaç yüz satır mı yoksa milyonlarca satır mı üreteceğine dair tahmini, Optimizer'ın hangi JOIN algoritmasını (Nested Loops, Hash, Merge) seçeceğini doğrudan belirler.
Optimizer için Önemi
SQL Server Query Optimizer, bir sorgu için mümkün olan binlerce yürütme planı arasından en düşük tahmini maliyete sahip olanı seçmekle görevlidir. Bu maliyet modelinin neredeyse tamamı, CE tarafından sağlanan cardinality tahminleri üzerine inşa edilmiştir. Dolayısıyla, doğru bir cardinality tahmini olmadan, maliyet hesabı anlamsızlaşır ve Optimizer verimsiz planlar seçebilir.
Yanlış tahminler, performansı felç eden sorunlara yol açar: tahmini satır sayısı gerçekten çok düşükse, Optimizer bellek yoğun işlemler için yetersiz bellek tahsisi (Memory Grant) yaparak tempdb'ye taşma (spill) yaşanmasına neden olur. Tahminin aşırı yüksek olması durumnda ise, daha yavaş ama çok sayıda satıra uygun olduğu düşünülen algoritmalar (örneğin, Hash Join yerine Nested Loops) seçilebilir. Bu nedenle, CE'nin doğruluğu, genel veritabanı performansının en temel belirleyicilerinden biridir.
Tarihsel Evrimi
SQL Server'ın cardinality tahmin mantığı, ürünün tarihi boyunca iki büyük paradigma değişikliği yaşamıştır. SQL Server 7.0'dan 2012 sürümüne kadar kullanılan orijinal CE ("70 modeli"), temel istatistiksel varsayımlara dayanıyordu. Bu model, modern iş yüklerinin karmaşıklığı karşısında giderek yetersiz kalmaya başladı.
SQL Server 2014, devrim niteliğinde yeni bir Cardinality Estimator ile birlikte geldi. Bu yeni model ("120 modeli"), veri dağılımlarının artık daha homojen olmadığı gerçeğini daha iyi yansıtan güncellenmiş varsayımlar ve daha gelişmiş algoritmalar getirdi. Örneğin, çoklu yüklemlerde (multiple predicates) bağımsızlık varsayımını daha muhafazakar bir şekilde ele alır ve JOIN işlemlerindeki cardinality hesabını iyileştirdi. Bu değişiklik, birçok sorguda performansı önemli ölçüde artırdı.
| Özellik | Eski CE (70 Modeli) | Yeni CE (120+ Modeli) |
|---|---|---|
| Varsayılan Başlangıç | SQL Server 7.0 | SQL Server 2014 |
| Çoklu Yüklem Varsayımı | Tam Bağımsızlık | Kısmi Bağımlılık (Exponential Backoff) |
| JOIN Cardinality | Basit Containment Varsayımı | Basit Varsayım, Basit Olmayan Containment Desteği |
Ancak, bu değişiklik bazı mevcut uygulamalarda gerilemelere de neden olduğu için, Microsoft uyumluluğu korumak adına eski modelin de kullanılmasına izin verdi. SQL Server 2016 ve sonrasında, sorgu düzeyinde QUERYTRACEON ipucu veya veritabanı uyumluluk seviyesi (compatibility level) ile hangi modelin kullanılacağı seçilebilir. Bu evrim, CE'nin statik bir bileşen olmadığını, veri modelleri ve sorgulama kalıpları geliştikçe sürekli iyileştirildiğini göstermektedir.
Çalışma Mantığı ve İstatistikler
CE'nin tahmin yapabilmesi için gerekli ham veriler, istatistik nesneleri tarafından sağlanır. Bu istatistikler, bir sütun veya sütun kümesindeki değerlerin dağılımını tanımlyan histogramlar, yoğunluk vektörleri ve temel bilgiler içerir. Histogram, ilk sütun için eşit aralıklı en fazla 200 adet "step" (basamak) tutar ve her step'te belirli bir aralıktaki değerlerin sıklığını ve yaklaşık benzersiz değer sayısını (RANGE_ROWS, EQ_ROWS, DISTINCT_RANGE_ROWS) saklar.
CE, bir WHERE yüklemi (örneğin, WHERE ColumnX > 100) ile karşılaştığında, ilgili istatistiğin histogramını sorgular. Eğer yüklemin değeri bir step'in tam sınırına denk geliyorsa, tahmin doğrudan ve kesindir. Ancak, değer step'ler arasında bir yerdeyse, CE doğrusal enterpolasyon (linear interpolation) gibi matematiksel yöntemlerle bir tahminde bulunur. Bu noktada, CE'nin "varsayım"ları devreye girer.
- Bağımsızlık Varsayımı: Farklı sütunlardaki filtrelerin birbirinden bağımsız olduğu varsayılır. Örn: P(Şehir='Ankara' AND Yaş>30) = P(Şehir='Ankara') * P(Yaş>30). Yeni CE, bu varsayımı daha az agresif uygular.
- Benzersizlik (Uniformity) Varsayımı: Histogram step'leri içindeki değerlerin eşit dağıldığı varsayılır.
- Containment Varsayımı: JOIN işlemlerinde, birleştirme sütunundaki eşleşen değerlerin ("in" ilişkisi) varlığına dair varsayım. Basit containment, değerlerin eşit dağıldığını kabul eder.
| İstatistik Bileşeni | Açıklama | CE'deki Kullanım Amacı |
|---|---|---|
| Histogram | İlk sütunun değer aralıklarını ve frekanslarını saklar. | Eşitlik (=) ve Aralık (>, <, BETWEEN) filtrelerinin seçiciliğini tahmin etmek. |
| Yoğunluk (Density) | Sütun veya sütun kombinasyonundaki benzersiz değerlerin ortalama seçiciliği (1/distinct_count). | Eşit olmayan (inequality) yüklemler veya histogramın olmadığı durumlar için genel tahmin. |
| String Index İstatistikleri | Metin sütunlarındaki ortalama uzunluk gibi bilgiler. | LIKE yüklemi gibi metin aramalarının seçiciliğini modellemek. |
İstatistiklerin doğruluğu ve güncelliği, CE'nin performansının anahtarıdır. Eskimiş istatistikler, gerçek veri dağılımını yansıtmadığı için, CE'nin yanlış tahminler yapmasına ve dolayısıyla kötü plan seçimlerine yol açar. Bu nedenle, istatistiklerin otomatik güncelleme stratejileri veya düzenli bakım işleri ile yönetilmesi kritik bir veritabanı yönetimi görevidir.
Yaygın Zorluklar ve Yanlış Tahminler
Cardinality Estimator'ın doğruluğunu tehdit eden ve performans sorunlarının temel nedeni olan birkaç yaygın senaryo bulunmaktadır. Bunların başında, CE'nin matematiksel varsayımlarının gerçek veri ilişkileriyle örtüşmediği durumlar gelir. Örneğin, güçlü korelasyona sahip sütunlar üzerindeki çoklu filtreler, bağımsızlık varsayımı nedeniyle dramatik şekilde yanlış tahminlere yol açabilir. "Ülke='Türkiye' AND Şehir='İstanbul'" filtrelemesinde, bu iki sütun pratikte bağımlı olduğu halde, CE filtrelerin seçiciliğini çarparak aşırı iyimser (çok düşük satır) bir tahmin yapabilir.
Parametreleştirilmiş sorgular ve parametre duyarsızlığı (parameter sniffing) sorunu, bir diğer kritik zorluktur. Optimizer, bir sorgunun ilk derlenişinde gelen parametre değerine göre bir plan oluşturur. Eğer bu ilk değer, sütun istatistiklerindeki dağılımı temsil etmiyorsa (örneğin, çok seçici bir değer), oluşturulan plan diğer, daha az seçici parametre değerleri için felaket derecede verimsiz olabilir. CE, derleme anındaki tek bir değere göre tahmin yaptığı için, planın tüm olası parametreler için optimal olmasını garanti edemez.
Sıra dışı veri dağılımları, histogramın sınırlamaları nedeniyle sorun yaratır. 200 basamaklık histogram, milyarlarca benzersiz değere sahip bir sütundaki tüm varyasyonları yakalayamaz. Değerler eşit dağılmadığında ve sık sık güncellendiğinde, istatistikler hızla geçersiz hale gelebilir. Ayrıca, LIKE yüklemi ile yapılan joker karakter aramaları veya kullanıcı tanımlı fonksiyonların (UDF) WHERE cümlesinde kullanılması gibi durumlarda, CE'nin seçicilik için güvenilir bir modeli yoktur ve genellikle sabit, gerçeği yansıtmayan bir yüzde tahmini kullanır.
Performans İyileştirme Yöntemleri
Yanlış cardinality tahminlerinden kaynaklanan performans sorunlarını azaltmak veya ortadan kaldırmak için bir dizi gelişmiş teknik ve yapılandırma seçeneği mevcuttur. Bu yöntemler, temel olarak CE'ye daha iyi bilgi sağlamaya veya onun varsayımlarının olumsuz etkilerini sınırlamaya odaklanır. En temel ve kritik adım, istatistiklerin doğru ve güncel kalmasını sağlamaktır. Bu, AUTO_UPDATE_STATISTICS seçeneğinin açık olması ile sağlanabilir, ancak büyük tablolar veya kritik iş yükleri için daha sık güncelleme sıklığı belirleyen bakım planları gerekli olabilir.
Daha karmaşık senaryolarda, çok sütunlu istatistikler (multi-column statistics) oluşturmak, CE'ye sütunlar arasındaki korelasyon hakkında bilgi verebilir. Ancak bu istatistikler yalnızca ilk sütun için histogram sağlar, diğer sütunlar için yalnızca korelasyon bilgisi tutar. Daha kesin bir kontrol için, sorgu düzeyinde ipuçları (query hints) kullanılabilir. Örneğin, OPTIMIZE FOR ipucu ile Optimizer'a belirli bir parametre değerine göre plan oluşturması söylenebilir veya daha radikal bir çözüm olarak, gerçek cardinality değerini zorlamak için USE HINT ('FORCE_LEGACY_CARDINALITY_ESTIMATION') gibi ipuçları ile CE modeli geçici olarak değiştirilebilir.
SQL Server 2016 ve sonrasında sunulan ve bu konuda en güçlü araçlardan biri olan Sorgu Saklama (Query Store), performans regresyonlarını izlemek ve belirli bir sorgu için "zorlanmış" bir plan seçmek için kullanılabilir. Bu, parametre duyarsızlığından kaynaklanan sorunlara pratik bir çözüm sunar. Ayrıca, gelişmiş seçicilik bilgisi gerektiren karmaşık filtreler için, hesaplanmış sütunlar (computed columns) üzerinde istatistik oluşturma veya plan kılavuzları (plan guides) gibi daha ileri düzey tekniklere başvurulabilir. Nihai çözüm, uygulama katmanında sorgu tasarımını, mümkünse CE'nin modelleyebileceği daha basit ve tahmin edilebilir kalıplara uyacak şekilde revize etmektir.