Sql Server Where ve Join Filtreleri Karşılaştırma
Bilgisayar Programcılığı dünyasında genellikle bir işi yapmanın birden fazla yolu vardır. Özellikle veritabanı tarafında bu yollar daha da fazla olabilir. Uygulama Geliştiriciler olarak yeni bir kod parçası yazacağımız zaman, genellikle bu yollardan en çok kullandığımız bir tanesini seçeriz ve onu kullanırız.
Ne var ki, seçtiğimiz yol herzaman en doğru yol olmayabilir. Sql‘de join‘li sorgulama yaparken, filtreleme için kullandığımız yöntem de bunlardan biri olabilir.
Bu yazımda join‘li sorgularda filtreleme için seçebileceğimiz iki yolu karşılaştıracağım. Karşılaştırma yapmak için kendi bilgisayarımda kurulu olan Sql Server 2008 üzerinde AdventureWorkd2008 R2 veritabanını kullandım.
Eğer birden fazla tablonun join‘ler ile ilişkilendirildiği bir sorgu yazıyorsak, sonuç kümesini filtreleme için kullanabileceğimiz iki yöntem vardır;
WHERE Filtreleme
Sonuç kümesinde olmasını/olmamasını istediğimiz kayıtları sorgunun WHERE cümlesinde tanımlarız. Şablon;
SELECT [TABLE1.ALANADLARI], [TABLE2.ALANADLARI] FROM [TABLE1] JOIN [TABLE2] ON [TABLE1.ALAN1] = [TABLE2.ALAN1] WHERE [TABLE1.ALAN2] = DEGER AND [TABLE2.ALAN2] = DEGER
JOIN Filtreleme
Sonuç kümesinde olmasını/olmamasını istediğimiz kayıtları sorgunun JOIN cümlelerinde tanımlarız. Şablon;
SELECT [TABLE1.ALANADLARI], [TABLE2.ALANADLARI] FROM [TABLE1] JOIN [TABLE2] ON [TABLE1.ALAN1] = [TABLE2.ALAN1] AND [TABLE1.ALAN2] = DEGER AND [TABLE2.ALAN2] = DEGER
AdventureWorks2008 R2 veritabanında aşağıdaki iki sorguyu çalıştırdıktan sonra, performans analizini yapalım;
WHERE Filtreleme
SELECT * FROM Sales.SalesOrderHeader AS SOH WITH (NOLOCK) JOIN Sales.SalesOrderDetail AS SOD WITH (NOLOCK) ON SOH.SalesOrderID = SOD.SalesOrderID JOIN Sales.SalesOrderHeaderSalesReason AS SOHSR WITH (NOLOCK) ON SOHSR.SalesOrderID = SOH.SalesOrderID JOIN Sales.SalesReason AS SR WITH (NOLOCK) ON SOHSR.SalesReasonID = SR.SalesReasonID WHERE SOH.CustomerID > 15000 AND SOD.LineTotal > 2000 AND SR.SalesReasonID > 5
JOIN Filtreleme
SELECT * FROM Sales.SalesOrderHeader AS SOH WITH (NOLOCK) JOIN Sales.SalesOrderDetail AS SOD WITH (NOLOCK) ON SOH.SalesOrderID = SOD.SalesOrderID AND SOH.CustomerID > 15000 AND SOD.LineTotal > 2000 JOIN Sales.SalesOrderHeaderSalesReason AS SOHSR WITH (NOLOCK) ON SOHSR.SalesOrderID = SOH.SalesOrderID JOIN Sales.SalesReason AS SR WITH (NOLOCK) ON SOHSR.SalesReasonID = SR.SalesReasonID AND SR.SalesReasonID > 5
Her iki sorgu da çalıştıktan sonra 1321 satır geri döndürdü. Performans incelemesini üç alanda yapacağız;
- CPU Kullanımı
- Disk Kullanımı
- Hafıza Kullanımı
Bu üç performans kriteri için verileri SYS.SYSPROCESSES DMV’sinden alabiliriz. SYS.SYSPROCESSES için detaylı bilgiye MSDN‘deki şu makaleden ulaşabilirsiniz. Aşağıda ilgili üç performans kriteri için verileri elde edebileceğimiz sorgu var;
SELECT DB_NAME(SP.DBID) AS VERITABANI, EST.TEXT AS SORGU, CPU, PHYSICAL_IO AS DISK_OKUMA, MEMUSAGE AS HAFIZA_KULLANIM FROM SYS.SYSPROCESSES AS SP CROSS APPLY SYS.DM_EXEC_SQL_TEXT(SP.SQL_HANDLE) AS EST
Bu sorguyu çalıştırdıktan sonra benim test bilgisayarımda şu verileri elde ettim;
- VERITABANI : AdventureWorks2008R2
- CPU : 1965
- DISK_OKUMA : 211
- HAFIZA_KULLANIM : 2
- VERITABANI : AdventureWorks2008R2
- CPU : 156
- DISK_OKUMA : 0
- HAFIZA_KULLANIM : 2
Gördüğünüz gibi kaynak kullanımı açısından (özellikle Disk Okuma ve CPU Kullanımı açısından) JOIN Filtreleme, WHERE Filtrelemeden daha avantajlı.
JOIN Filtreleme tabloları eşlerken filtrelenmiş verileri kullanıyor, WHERE Filtreleme ise, önce tabloları eşleştiriyor sonra filtreliyor. Özellikle çok kayıt bulunan/bulunacak olan tablolarınıza sorgu yazarken, JOIN Filtreleme’yi kullanmanızı tavsiye ederim.
Son paragrafın ilk cümlesini teyit edebileceğimiz bir Microsoft adresi var mı Engin?
Yazıların başarılı bu arada, tebrikler.