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] = DEGERAdventureWorks2008 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 > 5JOIN 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 > 5Her 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