- Zamanla SQL Server çok RAM kullanıyor, bunu düzeltmek için,
- CPU kullanımı zaman zaman tavan yapıyor, sunucuyu yeniden başlatınca düzeliyor,
- Tam emin değiliz; ama zamanla SQL Server'da çalışan sorgular yavaşlıyor, yeniden başlatmak sorunları çözüyor.
- Sizden önceki gelen danışman veya X arkadaş böyle tavsiye etti,
Bahsettiğim senaryoda aldığım yanıtlar aşağı yukarı hep böyle. Bu yanıtları özellikle numaralandırdım, çünkü aşağıda tek tek özetle açıklayacağım.
1- SQL Server kurulumlarında varsayılan olarak SQL Server sunucuda varolan tüm hafıza kaynağını kullanmak üzere ayarlıdır ve doğası gereği sadece SQL Server değil, tüm veritabanı sistemleri olabildiğince RAM kullanmak ister. Ne kadar çok işlem diskten değil de doğrudan hafızadan yapılabilirse, işlemler o kadar hızlı gerçekleşir.
İşletim sistemi, SQL Server'ın kendi diğer bileşenleri veya sunucu üstündeki diğer uygulamaların da hafıza ihtiyacı vardır ve SQL Server yapılandırması da bu çerçevede ayarlanmalıdır. Aksi takdirde "Paging / Swap" oluşur, bu da uygulamaların ağır çalışmasına, yani performans sıkıntılarına neden olur. Çünkü yetersiz hafıza kaynağı nedeniyle uygulamalar çatışır ve Windows işletim sisteminin Page File'ı kullanılmaya başlanır. Yani hafıza (RAM) yerine bazı uygulamalar için fiziksel disk hafıza niyetiyle kullanılmaya başlanır, ki bu yöntem hafızaya göre defalarca kat yavaştır. Donmalara, uzun süreli beklemelere neden olur.
2- Bunun nedeni genellikle "Parameter sniffing"tir. Parameter sniffing normal şartlar altında kendi başına bir sorun değildir, ama planlar anormal değerlere göre derlendiğinde parameter sniffing can yakabilir. Her sorgu çalışmadan önce o sorgu için bir çalıştırma planı (Execution Plan) oluşturulur ve bu çalıştırma planı da sorgu çalıştırılırken kullanılan ilk parametre değerine göre oluşturulur. Çalıştırma planı Plan Cache'te konumlandıktan sonra (parameterize sorgular, stored procedure'ler ve diğer basit sorgular gibi) ilgili sorgular artık bu planı kullanarak çalışır. Eğer plan en uygun şekilde ve en genel talebe hitap edecek değerlerle oluşmadıysa, kötü bir performans ile çalışabilir ve bu da CPU'nun ve diğer donanım kaynaklarının verimsiz olarak kullanılmasına neden olabilir.
Plan Cache'i boşalttığınızda veya SQL Server servisini yeniden başlattığınızda (veya bazı SQL Server Instance'ı düzeyinde ayarı değiştirdikten sonra veya tekil bir planı Plan Cache'ten sildikten sonra) sorunlu çalıştırma planı gitmiş olur ve ilgili sorgu veya stored procedure ilk çalıştırışınızda yeni bir plan oluşturulur. Şansınıza yeni plan daha uygun değerler kullanılarak oluşturulabileceği için o anda "sorun çözüldü" sanabilirsiniz. Fakat Plan Cache'in bir dahaki sıfırlanışında veya herhangi başka bir nedenle ve zamanda bu plan yeniden kötü bir şekilde derlendiğinde yine bu sorunu yaşarsınız.
Yani sunucuyu veya SQL Server servisini kapatıp açmak kalıcı bir çözüm değildir, bu nedenle sürekli kapatıp açmaya devam edersiniz.
3- Bunun nedeni genellikle ya 2. maddede açıkladığım neden veya sorguların bloklanması (blocking) kaynaklı oluyor. Haliyle sunucu veya servis yeniden başlatılırken tüm bloke eden sorgular da sonlandırılmış oluyor ve servis yeniden başlayınca bloke olma sorunu "çözülmüş" oluyor.
4- Eğer bir danışman veya X arkadaş ilk 3 maddede yaşanılan sorunlar için size en iyi pratik olarak "SQL Server servisini veya sunucusunu düzenli olarak yeniden başlatmayı" veya "Cache'leri boşaltmayı" önerirse arkanıza bakmadan kaçın. Tabii ofis ve ortam sizin olacağı için kaçamayacağınıza göre "arkadaşa" veya her ne sıfatla size bunu öneriyorsa ona bir çay ısmarlayıp nazikçe konuyu düşüneceğinizi iletebilir ve numarasını telefonunuzdan silebilirsiniz.
Peki "Cache"lerin boşaltılması neden kötü?
- Ad-hoc ve dinamik olmayan, parameterize olan tüm sorguların ilk çalışışlarında bir çalıştırma planı oluşturulur ve (sunucu ayarlarınıza göre) bu plan ilk veya ikinci seferinde Plan Cache'te konumlandırılır. Daha sonra ilgili sorgu / stored procedure her çalıştığında bu planı kullanır. Çalıştırma planının oluşturulma işlemi CPU yüklü bir işlemdir. Eğer sık sık Plan Cache'i boşaltırsanız veya ilgili sorgu her çalıştığında planın yeniden derlenmesini sağlarsanız sık sık tüm ilgili işlemler için yeniden çalıştırma planı oluşturulması gerekir ve bu da işlemlerinizin anlık olarak yavaşlamasına, genel olarak sunucu işlemci masraflarınızın artmasına neden olur.
- SQL Server'da geleneksel (In-memory / Hekaton olmayan) bir tablodaki kayıtlar için işlem yapacağınız zaman bu işlem hafızada (RAM) yapılır ve daha sonra Lazy Writer veya Checkpoint ile diske aktarılır. Update, Delete ve Insert hangi DML komutu çalıştırırsanız çalıştırın, ilgili kayıtlar önce hafızada değiştirilir doğrudan diskteki kayıt değiştirilmez. Eğer değişiklik yapılmak istenen kayıtlar Data Cache'te / Buffer Pool'da yoksa, önce diskten okunur ve Buffer Pool'a getirilir ve kayıtlardaki değişiklik hafızada yapılır (bu durumda ilgili kayıtlar "Dirty Page" olur). Select için de aynı şey söz konusu, sorguladığınız kayıtları içeren Page'ler hafızada yoksa önce diskten Buffer Pool'a taşınır ve sorgunuz ondan sonra cevap verir. Bu nedenle işlem yapılacak kayıtların ne kadar çoğu hafızadaysa, işlemler o kadar hızlı gerçekleşir. Eğer siz düzenli olarak Buffer Pool / Data Cache'i boşaltırsanız, bu sefer her seferinde, her kayıt için önce diske gidip o kayıtları hafızaya yüklemek gerekiyor. Böyle bir ortamda da bol bol PAGEIOLATCH bekleme tipleri görürsünüz, çünkü diskleriniz harıl harıl çalışır durur, kullanıcılar yavaşlık hisseder. Bazı senaryolarda Deadlock ve Blocking'in nedeni de budur.
Veritabanı sunucunuzu sürekli yeniden başlatarak ve Cache'leri düzenli olarak boşaltarak sorunları sadece ötelemiş olursunuz. Bu sorunları çözmek için SQL Server Instance'larınızın doğru yapılandırılması, sorunlu sorguların iyileştirilmesi, çalıştırma planlarının çeşitli tekniklerle istikrarlı hale getirilmesi ve gerekiyorsa dondurulması gerekiyor. Yukarıda maddeler halinde sıraladığım sorunların tek çözümü budur.
Ekrem Önsoy
Microsoft SQL Server Danışmanı