İÇİNDEKİLER
- •Compatibility level yükseltmesini plan regresyonu yaşamadan yapalım
- •SQL Server Sürümlerine Göre Compatibility Level
- •Compatibility Level Aslında Neyi Kontrol Eder?
- •Seviyeyi Yükseltmek Sorguları Neden Yavaşlatabilir?
- •Plan Cache’e Ne Olur?
- •Query Store ile Güvenli Yükseltme Adımları
- •1. Motoru yükseltin, eski seviyeyi koruyun
- •2. Query Store’u açın ve baseline toplayın
- •3. Compatibility level’ı yükseltin
- •4. Gerilemeleri bulun ve düzeltin
- •5. Geçici çözümleri zamanla kaldırın
- •Eski Bir Seviyede Ne Zaman Kalınmalı?
- •Compatibility Level Kontrol Listesi
- •Bir upgrade ya da compatibility level değişikliği mi planlıyorsunuz?
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.
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.
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ı,
modelveritabanı 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_HOTFIXESdatabase 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.
İlgili Yazılar
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.