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</pre> 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;
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 Filtreleme**den 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.
Senior Software Engineer, @Microsoft
Ada ve Ege'nin babası ;)
Makale Adedi: 484