Bu iki komut ta aynı işi yapıyor. Görev olarak hiç bir farkları yok. Özellik olarak benim karşılaştığım bir fark oldu.
Eğer yazdığımız sorguda bir tabloya link server ile bağlanıyor isek (NOLOCK) kulanırsak sorgu hata alıyor ama WITH(NOLOCK) hatasız çalışıyor.
Ek olarak, Microsoft, WITH(NOLOCK) ın kullanılmasını öneriyor.
Translate
27 Nisan 2015 Pazartesi
24 Nisan 2015 Cuma
SQL Server - REMOTE JOIN - Performans
Bir tabloyu(Tablo1) Arsiv deki başka bir tablo(Tablo2History) ile JOIN lemek istiyoruz. Ana makinedeki Tablo1 de 1000 kayıt olsun. Arsiv Makinesinde bulunan Tablo2History tablosunda da 10 milyon kayıt olsun. JOIN işleminde Link Server kullanalım ve kullanacağımız Link Server ismi ArsivDB olsun.
Normalde aşağıdaki gibi bir sorgu yazarız. JOIN işleminde Tablo2History deki tablodan sadece birkaç kayıt geleceğini biliyor olalım.
SELECT * FROM Tablo1 T WITH(NOLOCK)
INNER JOIN ArsivDB.dbo.Tablo2History TH WITH(NOLOCK) ON (TH.Tarih = T.Tarih)
Yukardaki sorkuda işleyiş şu şekilde oluyor:
1- Tablo2History tablosunda bulunan 10 milyon kayıt Arşiv Makinasından Ana Makineye taşınıyor.
2- JOIN işlemi Ana Makinede yapılıyor ve eşleşen bir kaç kayıt listeleniyor.
Yani bir kaç kayıt listelemek için 10 milyon kaydı ana makineye taşıyarak çok büyük külfet vermiş ve süreyi çok uzatmış oluyoruz.
Bunun yerine REMOTE komutunu sorguya ekleyerek performansı arttırmış oluruz.
Aşağıdaki gibi bir sorgu yazarsak
SELECT * FROM Tablo1 T WITH(NOLOCK)
INNER REMOTE JOIN ArsivDB.dbo.Tablo2History TH WITH(NOLOCK) ON (TH.Tarih = T.Tarih)
işleyiş şu şekilde oluyor:
1- Tablo1 tablosunda bulunan 1000 kayıt Ana Makinadan Arşiv Makinesine taşınıyor.
2- JOIN işlemi Arşiv Makinesinde yapılıyor ve eşleşen bir kaç kayıt Ana Makineye taşınarak listeleniyor.
REMOTE komutu sorguya şu görevi veriyor: JOIN işlemi sağdaki tablonun bulunduğu remote makinede yapılsın.
Normalde aşağıdaki gibi bir sorgu yazarız. JOIN işleminde Tablo2History deki tablodan sadece birkaç kayıt geleceğini biliyor olalım.
SELECT * FROM Tablo1 T WITH(NOLOCK)
INNER JOIN ArsivDB.dbo.Tablo2History TH WITH(NOLOCK) ON (TH.Tarih = T.Tarih)
Yukardaki sorkuda işleyiş şu şekilde oluyor:
1- Tablo2History tablosunda bulunan 10 milyon kayıt Arşiv Makinasından Ana Makineye taşınıyor.
2- JOIN işlemi Ana Makinede yapılıyor ve eşleşen bir kaç kayıt listeleniyor.
Yani bir kaç kayıt listelemek için 10 milyon kaydı ana makineye taşıyarak çok büyük külfet vermiş ve süreyi çok uzatmış oluyoruz.
Bunun yerine REMOTE komutunu sorguya ekleyerek performansı arttırmış oluruz.
Aşağıdaki gibi bir sorgu yazarsak
SELECT * FROM Tablo1 T WITH(NOLOCK)
INNER REMOTE JOIN ArsivDB.dbo.Tablo2History TH WITH(NOLOCK) ON (TH.Tarih = T.Tarih)
işleyiş şu şekilde oluyor:
1- Tablo1 tablosunda bulunan 1000 kayıt Ana Makinadan Arşiv Makinesine taşınıyor.
2- JOIN işlemi Arşiv Makinesinde yapılıyor ve eşleşen bir kaç kayıt Ana Makineye taşınarak listeleniyor.
REMOTE komutu sorguya şu görevi veriyor: JOIN işlemi sağdaki tablonun bulunduğu remote makinede yapılsın.
SQL Server - CROSS APPLY, OUTER APPLY - Performans
Bir sorguda ikinci bir tabloya JOIN yapmak istiyoruz yalnız o tablodan sadece eşleşen ilk kaydın gelmesini istiyoruz.
INNER JOIN yada LEFT JOIN de TOP 1 koyamıyoruz. CROSS APPLY ve OUTER APPLY yardımımıza yetişiyor.
CROSS APPLY -> INNER JOIN in dengi ve performansları aynı
OUTER APPLY -> LEFT JOIN in dengi ve performansları aynı
Örneğin Müşteri kayıtlarını tuttuğumuz bir tablomuz(Musteriler) ve müşterilerin hareketlerini logladığımız ikinci bir tablomuz(MusteriHareketLog) olsun.
Musteri tablomuzun verileri aşağıdaki gibi osun;
ID MusteriIsmi
1 Ahmet ASLAN
2 Orhan YILMAZ
3 Sevim KOKMAZ
...
MusteriHareketLog tablomuzun verileri de aşağıdaki gibi osun;
ID HaraketIsmi MusteriID TarihSaat
1 Giris 1 2015-04-20 15:00
2 İşlem1 1 2015-04-20 15:01
3 Giris 3 2015-04-21 16:00
4 İşlem2 3 2015-04-21 16:05
5 Giris 2 2015-04-23 11:30
6 İşlem3 2 2015-04-23 11:32
Müşterilerin listesini almak istiyoruz ve bu listede son yaptığı işlemin tarih ve saatini de görmek istiyoruz. Eğer müşteri ve MusteriHareketLog tablolarını JOIN lersek bütün logları listelemiş oluruz. Bu bizim istediğimiz değil, istediğimiz liste için aşağıdaki gibi bir sorgu yazmamız yeterli oluyor
SELECT * FROM Musteri M WITH(NOLOCK)
CROSS APPLY(
SELECT TOP 1 TarihSaat FROM MusteriHareketLog L WITH(NOLOCK)
WHERE L.MusteriID = M.ID ORDER BY TarihSaat DESC
) T
INNER JOIN yada LEFT JOIN de TOP 1 koyamıyoruz. CROSS APPLY ve OUTER APPLY yardımımıza yetişiyor.
CROSS APPLY -> INNER JOIN in dengi ve performansları aynı
OUTER APPLY -> LEFT JOIN in dengi ve performansları aynı
Örneğin Müşteri kayıtlarını tuttuğumuz bir tablomuz(Musteriler) ve müşterilerin hareketlerini logladığımız ikinci bir tablomuz(MusteriHareketLog) olsun.
Musteri tablomuzun verileri aşağıdaki gibi osun;
ID MusteriIsmi
1 Ahmet ASLAN
2 Orhan YILMAZ
3 Sevim KOKMAZ
...
MusteriHareketLog tablomuzun verileri de aşağıdaki gibi osun;
ID HaraketIsmi MusteriID TarihSaat
1 Giris 1 2015-04-20 15:00
2 İşlem1 1 2015-04-20 15:01
3 Giris 3 2015-04-21 16:00
4 İşlem2 3 2015-04-21 16:05
5 Giris 2 2015-04-23 11:30
6 İşlem3 2 2015-04-23 11:32
Müşterilerin listesini almak istiyoruz ve bu listede son yaptığı işlemin tarih ve saatini de görmek istiyoruz. Eğer müşteri ve MusteriHareketLog tablolarını JOIN lersek bütün logları listelemiş oluruz. Bu bizim istediğimiz değil, istediğimiz liste için aşağıdaki gibi bir sorgu yazmamız yeterli oluyor
SELECT * FROM Musteri M WITH(NOLOCK)
CROSS APPLY(
SELECT TOP 1 TarihSaat FROM MusteriHareketLog L WITH(NOLOCK)
WHERE L.MusteriID = M.ID ORDER BY TarihSaat DESC
) T
SQL Server - CTE (Common Table Expressions) WITH TableName AS - Performans
Bir tabloyu aynı sorguda birden fazla okumamız gerektiğinde, yani recursive erişim gerektiğinde CTE çok kullanışlı olmaktadır.
Örneğin bir Menu tablonuz olsun. Aynı tabloda ana menu ve alt menuler aşağıdaki gibi tutuluyor olsun;
CREATE TABLE Menu(
ID INT,
Aciklama VARCHAR(50),
AnaMenuID INT
)
Bu tablonun verileri aşağıdaki gibi olsun;
ID Aciklama AnaMenuID
1 Raporlar 0
2 Alt Rapor1 1
3 Alt Rapor2 1
4 Alt Rapor3 1
5 İşlemler 0
6 Alt İşlem1 5
7 Alt İşlem2 5
8 Alt İşlem3 5
9 Alt İşlem4 5
Biz menu ismini ve ana menü ismini aynı satırda listelemek istersek bu tabloya recursive erişmemiz gerekecek ve bunun için CTE yi aşağıdaki gibi kullanabiliriz;
WITH tempMenuList AS -- Menu tablosu belleğe alınarak temp tablo oluşturulur
(
SELECT * FROM Menu WITH(NOLOCK)
)
-- Buradan sonrasında tempMenuList tablosunu istediğimiz gibi kullanabiliriz. Sadece SELECT
-- değil çeşitli ihtiyaçlarda UPDATE, DELETE, INSERT komutları da kullanılabilir.
SELECT M1.ID, M1.Aciklama, ISNULL(M2.Aciklama, '') 'AnaMenuAciklama'
FROM tempMenuList M1
LEFT JOIN tempMenuList M2 ON (M2.ID = M1.AnaMenuID)
CTE, sorgu sonucundan gelen verileri(bu örneğimizde Menu tablosunu) belleğe alarak recursive erişimde performansı artırmaktadır.
Örneğin bir Menu tablonuz olsun. Aynı tabloda ana menu ve alt menuler aşağıdaki gibi tutuluyor olsun;
CREATE TABLE Menu(
ID INT,
Aciklama VARCHAR(50),
AnaMenuID INT
)
Bu tablonun verileri aşağıdaki gibi olsun;
ID Aciklama AnaMenuID
1 Raporlar 0
2 Alt Rapor1 1
3 Alt Rapor2 1
4 Alt Rapor3 1
5 İşlemler 0
6 Alt İşlem1 5
7 Alt İşlem2 5
8 Alt İşlem3 5
9 Alt İşlem4 5
Biz menu ismini ve ana menü ismini aynı satırda listelemek istersek bu tabloya recursive erişmemiz gerekecek ve bunun için CTE yi aşağıdaki gibi kullanabiliriz;
WITH tempMenuList AS -- Menu tablosu belleğe alınarak temp tablo oluşturulur
(
SELECT * FROM Menu WITH(NOLOCK)
)
-- Buradan sonrasında tempMenuList tablosunu istediğimiz gibi kullanabiliriz. Sadece SELECT
-- değil çeşitli ihtiyaçlarda UPDATE, DELETE, INSERT komutları da kullanılabilir.
SELECT M1.ID, M1.Aciklama, ISNULL(M2.Aciklama, '') 'AnaMenuAciklama'
FROM tempMenuList M1
LEFT JOIN tempMenuList M2 ON (M2.ID = M1.AnaMenuID)
CTE, sorgu sonucundan gelen verileri(bu örneğimizde Menu tablosunu) belleğe alarak recursive erişimde performansı artırmaktadır.
17 Nisan 2015 Cuma
Merhaba Dünya
Ekrana "Merhaba Dünya" yazdırmakla başlayan Yazılım hayatımda karşılaştığım zorlukları ve çözümlerini paylaşmak istediğim bu sayfa benim de bazen açıp ne yapmıştım diye bakma ihtiyacımdan doğmuştur :)
Kaydol:
Kayıtlar (Atom)