Database cylinder with a slider and a gauge, representing the SQL Server database compatibility level setting

SQL Server Compatibility Level Nedir? Ne Değiştirir, Nasıl Güvenle Yükseltilir?

SQL Server compatibility level’ın gerçekte neyi kontrol ettiği, 150, 160 ve 170 seviyelerinde nelerin değiştiği, plan cache’e etkisi ve plan regresyonu yaşamadan Query Store ile yükseltme adımları.

Kasım 17, 2021

Her SQL Server veritabanının 150, 160 ya da 170 gibi bir compatibility level değeri vardır. Bu değer veritabanının hangi SQL Server sürümünde çalıştığını belirlemez. Veritabanının, üzerinde çalıştığı motordan hangi query optimizer ve T-SQL davranışını alacağını belirler. SQL Server 2025 üzerinde 130 seviyesindeki bir veritabanı 2025 motorunda çalışır, ama sorgularını büyük ölçüde SQL Server 2016 gibi planlar.

Bu yüzden compatibility level, her upgrade’deki en önemli ayardır. Yükseltmek yılların optimizer iyileştirmelerini açar; ama dün sorunsuz çalışan sorguların birden çok daha kötü bir plan seçebildiği adım da budur. Bu rehberde seviyenin neyi kontrol ettiğini, 150, 160 ve 170’te nelerin değiştiğini, seviye değiştiğinde plan cache’e ne olduğunu ve performans sürprizi yaşamadan yükseltmek için Query Store ile izlenecek adımları anlatıyoruz.

SQL Server Performans Danışmanlığı

Compatibility level yükseltmesini plan regresyonu yaşamadan yapalım

Aryasoft, Query Store ile baseline toplar, compatibility level'ı kontrollü şekilde yükseltir ve gerileyen sorguları plan zorlama veya Query Store hint'leriyle hızla düzeltir.

Destek Alın

SQL Server Sürümlerine Göre Compatibility Level

SQL Server sürümü Varsayılan seviye Desteklenen seviyeler
SQL Server 2025 170 170, 160, 150, 140, 130, 120, 110, 100
SQL Server 2022 160 160, 150, 140, 130, 120, 110, 100
SQL Server 2019 150 150, 140, 130, 120, 110, 100
SQL Server 2017 140 140, 130, 120, 110, 100
SQL Server 2016 130 130, 120, 110, 100
SQL Server 2014 120 120, 110, 100
SQL Server 2012 110 110, 100, 90

Bu tablodan üç kural çıkar:

  • Yeni veritabanları, model veritabanı daha düşük bir seviyeye ayarlı değilse motorun varsayılan seviyesini alır.
  • Eski bir sürümden restore ya da attach edilen bir veritabanı, yeni motor desteklediği sürece seviyesini korur. Yalnızca motoru yükseltmek sorgu davranışını değiştirmez.
  • Eski seviye desteklenmiyorsa veritabanı otomatik olarak desteklenen en düşük seviyeye yükseltilir. SQL Server 2025’e restore edilen 90 seviyesindeki bir veritabanı 100 olur.
-- Her veritabanının seviyesi ve motorun varsayılanı
SELECT
    d.name,
    d.compatibility_level,
    (SELECT compatibility_level FROM sys.databases WHERE name = N'model') AS model_level,
    CONVERT(int, SERVERPROPERTY('ProductMajorVersion')) * 10              AS engine_default
FROM sys.databases AS d
ORDER BY d.compatibility_level, d.name;

Not

Compatibility level geri dönmenizi sağlamaz. SQL Server 2025 üzerinde 130 seviyesindeki bir veritabanı yine de SQL Server 2016’ya restore ya da attach edilemez: fiziksel dosya formatı seviyeye değil, motor sürümüne aittir.

Compatibility Level Aslında Neyi Kontrol Eder?

Microsoft, planı etkileyen iki tür değişikliği her yeni sürümün varsayılan seviyesine bağlar:

  • Cardinality estimator (CE) değişiklikleri. CE, bir planın her adımının kaç satır döndüreceğini tahmin eder; join türleri, memory grant’ler ve paralellik bu tahminlere göre belirlenir. Yeni bir sürümdeki CE değişiklikleri yalnızca o sürümün varsayılan seviyesinde açılır. “Yeni” CE, SQL Server 2014 ile 120 seviyesinde geldi; o günden bu yana her sürüm onu geliştirdi.
  • Query optimizer düzeltmeleri. Önceki sürümler için yayınlanan optimizer düzeltmeleri, daha yeni varsayılan seviyede otomatik olarak açılır. Eski seviyelerde, trace flag 4199 ya da QUERY_OPTIMIZER_HOTFIXES database scoped configuration ile açmadığınız sürece kapalı kalırlar.

Bunların üzerine, intelligent query processing özelliklerinin çoğu da seviyeye bağlıdır:

Seviye Sürüm Açılan önemli davranışlar
140 2017 Adaptive join, multi-statement TVF’ler için interleaved execution, batch mode memory grant feedback
150 2019 Scalar UDF inlining, table variable deferred compilation, rowstore üzerinde batch mode, row mode memory grant feedback
160 2022 Parameter sensitive plan (PSP) optimization, cardinality estimation feedback, degree of parallelism feedback
170 2025 DML ve tempdb için PSP optimization, opsiyonel parametre plan optimizasyonu, REGEXP_LIKE gibi regular expression fonksiyonları, anahtar şifrelemede OAEP-256 padding

Compatibility level bazı T-SQL davranışlarını da korur. Örneğin 130 seviyesinden itibaren datetime‘dan datetime2‘ye örtük dönüşüm milisaniye kesirlerini hesaba katar ve 120 seviyesinden farklı değerler döndürür. Korumadığı şey ise kaldırılmış (discontinued) işlevlerdir: motordan çıkarılmış bir özellik, daha düşük bir seviyede geri gelmez.

Seviyeyi Yükseltmek Sorguları Neden Yavaşlatabilir?

Sorguların çoğu yeni CE ve optimizer altında aynı ya da daha iyi bir plan alır. Birkaçı almaz. Eski bir tahmine, tesadüfen işe yarayan bir istatistiğe ya da yeni modelin artık seçmediği bir plan şekline dayanan bir sorgu milisaniyelerden dakikalara gerileyebilir.

Bir compatibility level değişikliğinden sonraki tipik belirtiler şunlardır: CPU ya da süresi çok artmış birkaç sorgu, birden büyüyen memory grant’ler ya da spill’ler, önceden olmayan paralel planlar. Tehlike, bu birkaç sorgunun çoğu zaman en önemli sorgular olmasıdır: ay sonu raporu ya da en yoğun çalışan stored procedure gibi.

Plan Cache’e Ne Olur?

Compatibility level’ı değiştirmek, diğer birçok ALTER DATABASE işlemi gibi o veritabanının plan cache’ini geçersiz kılar. Veritabanındaki her sorgu ve stored procedure bir sonraki çalışmasında, bu kez yeni seviyenin kurallarıyla, yeniden derlenir.

Pratikte:

  • Değişikliğin hemen ardından bir derleme dalgası ve CPU artışı bekleyin. Yoğun bir OLTP sisteminde değişikliği sakin bir saatte yapın.
  • Değişiklikten hemen sonra o veritabanının plan cache’ini neredeyse boş görürsünüz. Bu beklenen bir durumdur, sorun işareti değildir.
  • Planlar “zamanla yavaş yavaş” değişmez; geçişten sonraki ilk çalışmada değişir. İlk saati yakından izleyin.
-- Veritabanı başına cache'teki planlar: değişiklikten önce ve sonra çalıştırın
SELECT
    DB_NAME(CONVERT(int, pa.value)) AS database_name,
    COUNT(*)                        AS cached_plans,
    SUM(cp.size_in_bytes) / 1024    AS size_kb
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_plan_attributes(cp.plan_handle) AS pa
WHERE pa.attribute = N'dbid'
GROUP BY pa.value
ORDER BY cached_plans DESC;

Query Store ile Güvenli Yükseltme Adımları

Microsoft’un önerdiği yaklaşım, değişikliği ölçülebilir ve sorgu bazında geri alınabilir kılmak için Query Store’u kullanır:

1. Motoru yükseltin, eski seviyeyi koruyun

Veritabanını mevcut compatibility level’ıyla yeni SQL Server sürümüne taşıyın. Uygulama eskisi gibi davranmalıdır. Böylece “yeni motor” sorunlarını “yeni optimizer” sorunlarından ayırırsınız.

2. Query Store’u açın ve baseline toplayın

ALTER DATABASE SalesDB SET QUERY_STORE = ON
(
    OPERATION_MODE = READ_WRITE,
    QUERY_CAPTURE_MODE = AUTO,
    MAX_STORAGE_SIZE_MB = 2048,
    CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 30)
);

Baseline’ın önemli sorguları içermesi için ay sonu ya da diğer yoğun dönem job’ları dahil tam bir iş döngüsü boyunca çalışmasına izin verin. Boyutlandırma ve yakalama ayarlarını Query Store best practice’leri yazımızda anlatıyoruz.

3. Compatibility level’ı yükseltin

ALTER DATABASE SalesDB SET COMPATIBILITY_LEVEL = 170;

4. Gerilemeleri bulun ve düzeltin

SSMS’teki Regressed Queries raporunu kullanın ya da Query Store’da değişiklik öncesi ve sonrası çalışma istatistiklerini karşılaştırın. Kök nedeni çözerken, gerileyen her sorgu için üç hızlı seçeneğiniz vardır:

-- Bilinen son iyi planı zorla
EXEC sys.sp_query_store_force_plan @query_id = 4711, @plan_id = 902;

-- Ya da yeni seviyede kalıp tek bir sorguyu eski optimizer davranışıyla çalıştır,
-- uygulama koduna dokunmadan
EXEC sys.sp_query_store_set_hints
     @query_id = 4711,
     @query_hints = N'OPTION (USE HINT(''QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_160''))';

-- Ya da tek bir sorgu için eski cardinality estimator'a dön
EXEC sys.sp_query_store_set_hints
     @query_id = 4711,
     @query_hints = N'OPTION (USE HINT(''FORCE_LEGACY_CARDINALITY_ESTIMATION''))';

İpucu

SSMS’teki Query Tuning Assistant bu akışı otomatikleştirir: baseline’ı toplar, seviyeyi yükseltir, gerilemeleri bulur ve sizin için hint’lerle deneme yapar. Sorguları tek tek incelemenin pratik olmadığı büyük veritabanlarında işe yarar.

5. Geçici çözümleri zamanla kaldırın

Zorlanan planlar ve hint’ler bir güvenlik ağıdır, nihai durum değil. Bunlara geri dönün: gerilemenin arkasındaki istatistik, index veya sorgu kalıbını düzeltin, ardından plan zorlamasını kaldırın.

Uyarı

Gerileyen tek bir sorguyu, veritabanının tamamını eski seviyeye döndürerek ya da tüm veritabanı için LEGACY_CARDINALITY_ESTIMATION’ı açarak çözmeyin. İkisi de diğer tüm sorgulardaki iyileştirmelerden vazgeçmek demektir. Uygulama üreticisi açıkça eski bir seviye istemiyorsa gerilemeleri sorgu seviyesinde düzeltin.

Eski Bir Seviyede Ne Zaman Kalınmalı?

Seviyeyi hemen yükseltmemek için geçerli nedenler vardır:

  • Uygulama üreticisi yalnızca belirli bir seviyeyi sertifikalandırıyor. ERP’ler ve paket yazılımlar bunu sıkça yapar; bir şeyi değiştirmeden önce kontrol edin.
  • Upgrade’den önce baseline toplamaya zaman yok. Önce motoru yükseltin, seviyeyi sonra yükseltin.
  • Kritik bir sorgu geriliyor ve düzeltmesi henüz yapamayacağınız kod değişiklikleri gerektiriyor. Seviyeyi koruyun ve değişikliği planlayın.

Eski bir seviyede de yeni motorun depolama, erişilebilirlik ve güvenlik iyileştirmelerinden yararlanırsınız; kaçırdığınız şey optimizer iyileştirmeleridir. Veritabanı seviyesinde QUERY_OPTIMIZER_HOTFIXES‘ı açmak, seviye değiştirmeden sürüm sonrası optimizer düzeltmelerini almanızı sağlar.

Compatibility Level Kontrol Listesi

  • Her veritabanının mevcut seviyesi, motor sürümüyle birlikte dokümante edildi.
  • Paket uygulamalar için üreticinin sertifikalandırdığı seviyeler teyit edildi.
  • Motor upgrade’i ve seviye değişikliği ayrı adımlar olarak planlandı.
  • Query Store açık ve tam bir iş döngüsünü kapsayan bir baseline’a sahip.
  • Seviye değişikliği, derleme dalgası beklenerek sakin bir zamanda yapılıyor.
  • Gerileyen sorgular veritabanı geri alınarak değil, plan zorlama veya Query Store hint’leriyle düzeltiliyor.
  • Zorlanan planlar ve hint’ler, kök nedenler çözüldükçe gözden geçirilip kaldırılıyor.
Veritabanının mevcut motor üzerinde hangi query optimizer ve T-SQL davranışlarını kullanacağını belirleyen bir veritabanı ayarıdır. Varsayılan değer SQL Server 2025’te 170, 2022’de 160, 2019’da 150’dir.
Hayır. Restore, attach ya da in-place upgrade edilen bir veritabanı mevcut seviyesini korur; yalnızca o seviye yeni motorda desteklenmiyorsa desteklenen en düşük seviyeye yükseltilir. Yeni veritabanları motorun varsayılan seviyesini alır.
Hayır. Hemen geçerli olur, o veritabanının plan cache’ini geçersiz kılar ve sorguların bir sonraki çalışmada yeniden derlenmesine yol açar; kısa bir CPU artışı bekleyin.
Hayır. Compatibility level yalnızca sorgu ve T-SQL davranışını değiştirir. Veritabanı dosya formatı motor sürümüne aittir; daha yeni bir sürümdeki veritabanı daha eskisine restore ya da attach edilemez.
Query Store ile gerileyen sorguları bulun; yalnızca bu sorgular için son iyi planı zorlayın ya da QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_n gibi bir Query Store hint’i ekleyin. Veritabanını yeni seviyede tutun ve kök nedeni zamanla düzeltin.

SQL Server Performans Danışmanlığı

Bir upgrade ya da compatibility level değişikliği mi planlıyorsunuz?

Aryasoft’un kıdemli DBA ekibi Query Store baseline’ını kurar, compatibility level’ı kontrollü bir pencerede yükseltir ve gerileyen sorguları aynı gün düzeltir; böylece yeni optimizer bir olay değil, performans kazancı olur.

4.7/5