MSSQL Server Execution Plan’da Karşılaşılan Cardinality Estimation Nedir

SQL Server Query Optimizer, bir sorguyu en verimli şekilde çalıştırmak için kaç satırın döneceğini önceden tahmin etmek zorundadır. Bu sürece Cardinality Estimation (CE) denir. Eğer bu tahmin yanlış yapılırsa, Optimizer yanlış operatörü (Örn: Index Seek yerine Scan) seçer ve performans felaketi yaşanır.

Mssql server execution plan yapısına baktığımızda genellikle Select yapısının üzerinde Sarı Ünlem işareti görülmektedir. İlgili bölümün üzerine mouse ile gelince Bu uyarı simgesinin neden kaynaklandığını tooltip penceresinden görebiliriz.

İlgili tooltip penceresine bakıldığında dönüşüm işlemlerinin execution plan seçimlerinde yanlış işlem yaptığını söylemektedir.

1. Plan-Affecting Convert ve SARGability Kaybı

Görselde yer alan CONVERT(nvarchar(30), [makbuz].[VERIGIRIS...]) ifadesi, SQL Server’ın karşılaştırma yapabilmek için tablo kolonunu çalışma anında dönüştürdüğünü gösterir. Bu durum sorgunun SARGable (Search Argumentable) yapısını bozar:

  • İndeks Kullanımı: Veri tipi dönüşümü kolon üzerinde yapıldığı için SQL Server, mevcut indeksleri doğrudan kullanamaz.
  • Arama Yöntemi: Bu uyarının sonunda belirtilen “SeekPlan” ifadesi, dönüşüm nedeniyle verimli bir “Index Seek” yerine daha maliyetli bir “Index Scan” (tüm indeksi okuma) yapılma ihtimalinin yüksek olduğunu gösterir.

2. İstatistiklerin Kör Noktası ve Tahminleme Hataları

SQL Server Query Optimizer, bir sorgunun ne kadar kaynak tüketeceğine elindeki istatistiklere bakarak karar verir. Ancak görseldeki uyarı, bu sürecin neden tıkandığını açıklar:

  • CardinalityEstimate Uyarısı: Tablo kolonu bir fonksiyon (CONVERT) içine alındığında, SQL Server elindeki istatistikleri (histogramları) bu yeni değerlerle eşleştiremez.
  • Yanlış Kaynak Ayrımı: “Karasallık Tahmini” (Cardinality Estimation) bozulduğunda, Optimizer dönecek satır sayısını yanlış tahmin eder. Bu da sorgu için gereğinden az veya çok bellek (memory grant) ayrılmasına, dolayısıyla performansın düşmesine neden olur.

3. Çözüm: Tahmin Doğruluğunu (CE) Artırmak

Bu teknik uyarıdan kurtulmak ve sorguyu en verimli hale getirmek için iki temel bilimsel yaklaşım uygulanmalıdır:

  • Veri Tipi Önceliği (Data Type Precedence): SQL Server’da veri tipleri arasında bir hiyerarşi vardır. NVARCHAR, VARCHAR’dan daha yüksek önceliklidir. Eğer parametre NVARCHAR ise, SQL Server düşük öncelikli olan tablo kolonunu (VARCHAR) yukarıya çekmek için otomatik dönüştürür. Çözüm, uygulama tarafındaki parametre tipini veritabanı kolonuyla birebir eşitlemektir.
  • Kolonu Saf Bırakmak: Filtreleme (WHERE) veya Join koşullarında kolon ismi üzerinde herhangi bir işlem (CONVERT, CAST, LEFT, vs.) yapmaktan kaçınılmalıdır. Dönüşüm gerekiyorsa, bu işlem kolon üzerinde değil, karşı taraftaki sabit değer veya parametre üzerinde yapılmalıdır.

Aşağıdaki komut ile belirtilen veritabanı üzerinde Cardinality Estimation olan ifadeleri göstermektedir. Aynı zamanda Sorgunun çalışma sayısının ve ortalama CPU tüketimini görebiliriz.

SELECT TOP 50
    DB_NAME(st.dbid) AS DatabaseName,
    st.text AS [Query Text],
    qp.query_plan,
    qs.execution_count,
    qs.total_worker_time / qs.execution_count AS [Avg CPU Time]
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.plan_handle) AS st
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) AS qp
WHERE 
    CAST(qp.query_plan AS NVARCHAR(MAX)) LIKE '%PlanAffectingConvert%'
    AND st.dbid = DB_ID('DB_NAME')
    AND st.text NOT LIKE '%sys.dm_exec_query_stats%'
ORDER BY qs.total_worker_time DESC;

Herhangi bir Query plan yapısına tıklandıktan sonra belirtilen Sarı ünlem işaretinin olduğunu görmüş oluruz.

Kısacası herhangi bir convert işlemi, başka bir işlem, etkileyebilir. Aynı zamanda missing index uyarıları da görülmektedir.

Başka makalede görüşmek dileğiyle..

“Biz ona şah damarından daha yakınız.” Kaf-16

Author: Yunus YÜCEL

Bir yanıt yazın

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