Pazartesi , 20 Kasım 2017

SQL Serverda Union veya Or Operatörünü Kullanmak

SQL Serverda bir sorgu yazarken her ne kadar sorgunun doğru sonucu getirmesi önemli olsa bile bunun yanında sorgularımızında performanslı bir şekilde çalışmasını isteriz. Küçük boyutlu veritabanlarında pek hissedilmese bile veri boyutunun fazla olduğu sistemlerde sorgu yazarken her ihtimal iyi değerlendirilip sorgular optimize edilmelidir.

Sorgu optimizasyonu yapılırken ilk incelenen ilgili sorgunun Execution Planıdır. Bildiğiniz gibi Execution Plan o sorgunun çalıştırılması sırasında SQL Server tarafından izlenecek yolu temsil eder. Her ne kadar SQL Server bu Execution Plan oluşturma işlemi kendisi yapsa bile biz de istersen bu planın istediğimiz şekilde oluşması için SQL Serverı zorlayabiliriz. Çoğu durumda SQL Server Execution Plan seçimi doğru yapsa bile bazı durumlarda Query Optimizer’ın yapısı gereği yanlış seçim yapabilmektedir. Bu durumlarda biri de sorgularımıza filtre olarak OR veya IN operatörü kullandığımız durumdur. Çünkü bu iki operatörün kullanılması sırasında iki değer arasındaki fark büyük ise SQL Server değerlendirirken büyük ihtimal Index veya Table Scan işlemini seçecektir. Fakat aynı sorgumuzu biraz değiştirerek Union veya Union All operatörü ile yazarak SQL Serverın Index veya Table Scan işlemi değil var olan bir index üzerinden Index Seek ile veriye hızlı bir şekilde erişimi sağlayabiliriz. Şimdi bu senaryoyu AdventureWorks üzerinde örnekleyelim.

SELECT  * FROM sales.SalesOrderDetail
WHERE ProductID = 776 OR ProductID = 879

Yukarıdaki sorgumuzun Execution Planı aşağıdaki gibidir.


sqlserverunion1

Yukarıdaki Execution Planı incelediğimizde Clustered Index Scan operatörü üzerinde tablodaki tüm kayıtların Scan edildiğini görebiliriz. Hatta bu Scan işleminden kurtulmak adına Query Optimizer bize bir de index önermektedir. Şimdi sorgumuzu aynı sonucu verecek şekilde UNION ile değiştirelim ve Execution Planı inceleyelim.

SELECT  * FROM sales.SalesOrderDetail
WHERE ProductID = 776
UNION
SELECT  * FROM sales.SalesOrderDetail
WHERE ProductID = 879

sqlserverunion2

Sorgumuzu Or yerine Union ile yazdığımızda yukarıdaki Execution planda da gördüğümüz gibi artık  SQL Server Clustered Index Scan yapmak yerine tablo üzeinde var olan Index üzerinde Seek işlemi yapmayı tercih etmiştir. Bunun en temel sebebi OR veya benzer olarak IN operatörü kullandığımızda SQL Server belli bir aralıkta veri okuyacaksa Index Seek yerine Scan işlemini tercih etmektedir. Fakat Union ile yazdığımız iki sorguyu ayrı ayrı değerlendirip ikisi içinde Index Seek yapabileceği Execution Planı kullanacaktır.

 

 

Hakkında ismailadar

Cevapla

E-posta adresiniz yayınlanmayacak. Required fields are marked *

*


*

Şu HTML etiketlerini ve özelliklerini kullanabilirsiniz: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>