MSSQL Server  OPTIMIZE FOR Query Hint Kavramıyla Execution Plan Müdahalesi

SQL Server’da yazdığımız sorgularda sıkça değişken veya parametreler kullanılmaktadır. Sorgumuzda değeri doğrudan kullanmak yerine değişken veya parametre kullandığımızda SQL Server Execution planı oluşturmak için istatistiklerin ortalama değerini kullanır. Bu sebeple sorgumuz ilk çalıştırıldığında oluşan Execution plan diğer parametre değerleri için de kullanılacak ve eğer yanlış bir Execution plan oluşturulmuşsa bundan sonraki tüm değerler için aynı Execution plan kullanılacaktır. Bu sebeple böyle durumlarda ilk defa oluşturulacak olan Execution planın hangi değer kullanılarak oluşturulacağı önem taşımaktadır. SQL Server’ın 2005 versiyonu ile beraber gelen OPTIMIZE FOR seçeneğini kullanarak sorgumuz ilk çalıştırıldığında oluşturulacak olan Execution plan için parametre değerlerini biz belirleyebilmekteyiz. Şimdi öncelikle parametre veya değişken kullanıldığı durumlarda SQL Server’ın nasıl davrandığını inceleyelim ve daha sonra OPTIMIZE FOR seçeneğini nasıl kullanacağımızı görelim.

SELECT SalesOrderID,ProductID 
 	,OrderQty 
FROM Sales.SalesOrderDetail 
WHERE ProductID = 796 
 

SELECT SalesOrderID,ProductID 
 	,OrderQty 
FROM Sales.SalesOrderDetail 
WHERE ProductID = 850 

Yukarıdaki sorgularımızın Execution planları aşağıdaki gibi olacaktır.

Yukarıdaki resimdeki Execution planlarımızı incelediğimizde sorgularımız yapısı aynı olsa dahi farklı ProductId değerleri için farklı Execution plan oluşmuştur. Şimdi ProductId değerini bir değişken ile sorgumuzda kullanalım.

DECLARE @ProductId INT = 796 
 
SELECT SalesOrderID,ProductID 
 	,OrderQty 
FROM Sales.SalesOrderDetail 
WHERE ProductID = @ProductId 
  
SET @ProductId = 850 
 
SELECT SalesOrderID,ProductID 
 	,OrderQty 
FROM Sales.SalesOrderDetail 
WHERE ProductID = @ProductId 

Değişken kullandığımız sorgularımızın Execution planları aşağıdaki gibi olacaktır.

Yukarıdaki resimde görüldüğü üzere değişken değerleri farklı olsa bile SQL Server her iki sorgu için de aynı Execution planı kullanacaktır. Bunun sebebi ise çalışma zamanında değişkenin değerine göre değil ortalama bir istatistik bilgisine göre Execution planın oluşturulmasıdır. Sık karşılaşılan bu durum özellikle Execution planı saklanan ve sürekli kullanılan Stored Procedure gibi yapılarda ilk oluşturulan Execution planın yanlış oluşmasına yol açabilmektedir. Böyle bir durumda ise OPTIMIZE FOR seçeneğini kullanarak sorgumuz ilk çalıştırıldığında oluşturulacak olan Execution plan için parametre değerlerini belirtebiliriz. Şimdi sorgumuzu aşağıdaki gibi çalıştıralım.

DECLARE @ProductId INT = 796 
SELECT SalesOrderID,ProductID 
 	,OrderQty 
FROM Sales.SalesOrderDetail 
WHERE ProductID = @ProductId 
OPTION(OPTIMIZE FOR (@ProductId = 850)) 

Sorgumuzun Execution planı aşağıdaki gibi olacaktır.

Yukarıdaki resimde gördüğümüz gibi sorgumuzda parametre veya değişken kullanmış olsak bile sorgumuzun Execution planı değişmiştir. Ayrıca sorgumuzun Execution planını XML olarak görüntülediğimizde Execution plan oluşturulurken ProductId olarak 850 değerinin kullanıldığını görebiliriz.

Sorgumuzun Execution planında @ProductId için gelen değerin 796 olmasına rağmen Execution plan oluşturulmasını için 850 değeri kullanılmıştır.

OPTIMIZE FOR seçeneği bazı durumlarda yararlı olup bu seçenek kullanılırken dikkat edilmesi gerekmektedir. Çünkü burada verdiğimiz parametre değerine göre Execution plan oluşmaktadır. Bu sebeple OPTIMIZE FOR seçeneğini genellikle tablodaki bir verinin düzgün dağıldığını fakat aralarından bir tanesinin bu dağılıma uymadığı durumlarda tercih etmemiz yararlı olacaktır. 

Bu makalede execution yapılarında görülen OPTIMIZE FOR Query Hintifadesine değinmiş olduk. Başka bir makalede görüşmek dileğiyle..

“Biz insana anne babasıyla ilgili öğütler verdik. Annesi, güçten kuvvetten düşerek onu karnında taşımıştır; çocuğun sütten kesilmesi iki yıl içinde olur. Bunun için (ey insan), hem bana hem anne babana minnet duymalısın; sonunda dönüş yalnız banadır.” Lokman-14

Author: Yunus YÜCEL

Bir yanıt yazın

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