MSSQL Server Execution Planda Görülen ExcessiveGrant Uyarısı

SQL Server’da bir sorgunun yürütme planını (Execution Plan) incelerken, SELECT operatörünün üzerinde sarı bir ünlem işareti ve tooltip penceresinde “The query memory grant detected ‘ExcessiveGrant’, which may impact the reliability.” uyarısını görmek, veritabanı motorunun “Senden çok fazla bellek istedim ama aslında bu kadarını kullanmadım” demesidir. Bu durum, ilk bakışta masum görünse de sunucu genelinde ciddi bir performans darboğazına işaret edebilir.

SQL Server, bir sorguyu çalıştırmadan önce (özellikle Sort veya Hash Join gibi işlemler varsa), bu işlemleri RAM üzerinde gerçekleştirmek için belirli bir miktar bellek rezervasyonu yapar. Buna Memory Grant denir.

ExcessiveGrant (Aşırı Tahsis) uyarısı, SQL Server Optimizer’ın sorgu için ayırdığı (Grant) bellek miktarı ile sorgunun gerçekten kullandığı (Used) bellek miktarı arasında uçurum olduğunda ortaya çıkar.

Detaylar:
• Memory Grant (İstenen): Initial 103032 KB
• Gerçek Kullanılan: Used 39004 KB

Bu, SQL Server’ın sorgu için yaklaşık 103 MB bellek ayırdığını, ama sadece ~39 MB’lık kısmını kullandığını gösteriyor.

Neden böyle bir şeyle karşılaşılır. Sebeplerini inceleyelim:

  • SQL Server, ne kadar bellek ayıracağına tablodaki verilerin istatistiklerine bakarak karar verir. Eğer istatistikler güncel değilse, Optimizer sorgudan 1 milyon satır döneceğini sanıp devasa bir bellek ayırabilir, oysa gerçekte sadece 10 bin satır dönüyordur.
  • Değişken uzunluklu sütunlar (örneğin VARCHAR(8000)) kullanıldığında, SQL Server bu sütunların her birinin yarısının dolu olduğunu varsayarak hesaplama yapar. Eğer bu alanlar aslında boş veya çok kısa veriler içeriyorsa, bellek tahmini aşırı yüksek çıkar.
  • İç içe geçmiş alt sorgular veya çok fazla tablo birleştirmesi, Optimizer’ın veri boyutunu hatalı tahmin etmesine (Cardinality Estimation hatası) neden olabilir.

İlgili işlemin sistemi zararları:

  • Resource Semaphore Beklemeleri: Eğer bir sorgu ihtiyacından fazla bellek rezerve ederse, aynı anda çalışan diğer sorgular bellek sırasına girer (RESOURCE_SEMAPHORE beklemesi). Bu, sunucunun kilitlenmesine veya yavaşlamasına neden olur.
  •  Daha Az Cache Alanı: Belleğin büyük bir kısmı boş yere rezerve edildiği için, SQL Server verileri RAM’de tutmak (Data Cache) yerine diskten okumaya başlar, bu da genel hızı düşürür.

Bu uyarıyı ortadan kaldırmak ve sistem sağlığını korumak için şu adımlar izlenmelidir.

  • İstatistikleri Güncelleyin: UPDATE STATISTICS [TabloAdi] komutu ile Optimizer’ın veri miktarını doğru tahmin etmesini sağlayın.
  • İndeks Kullanımı: Görseldeki sorgu ModifiedDate kolonuna göre sıralama yapıyor. Eğer bu kolonda bir indeks olsaydı, SQL Server veriyi zaten sıralı bulacağı için bir “Sort” işlemine ve dolayısıyla bellek tahsisine gerek duymayacaktı.
  • MAX_GRANT_PERCENT İpucu: Çok spesifik durumlarda, sorgu sonuna OPTION (MAX_GRANT_PERCENT = 10) gibi bir hint ekleyerek SQL Server’ın ayıracağı maksimum bellek miktarını kısıtlayabilirsiniz.
  • Veri Tiplerini Gözden Geçirin: Gerçekten ihtiyaç yoksa VARCHAR(MAX) veya çok geniş VARCHAR tanımlamalarından kaçının.

ExcessiveGrant uyarısı, sunucunuzun belleğinin verimsiz kullanıldığının açık bir kanıtıdır. Sorgularınızı optimize ederek bu bellek rezervasyonlarını düşürmek, sistemin aynı anda çok daha fazla sorguyu sorunsuz işlemesini sağlayacaktır.

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

“Andolsun zamana ki, insan gerçekten ziyan içindedir. Ancak iman edip de salih ameller işleyenler, birbirlerine hakkı tavsiye edenler, birbirlerine sabrı tavsiye edenler başka (onlar ziyanda değillerdir).” Asr Suresi

Author: Yunus YÜCEL

Bir yanıt yazın

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