Bu site emekli olmuştur. Arşiv amaçlı olarak BT AKADEMİ sponsorluğunda yayın hayatına devam etmektedir.




C#nedir?com
 
YAZAR HAKKINDA
Oğuz Yağmur
Oğuz Yağmur
http://www.oguzyagmur.com
İletişme geçmek için tıklayın.
26 Makalesi yayınlanmakta.
Yazar hakkında detaylı bilgi için tıklayın.
Yayınlanan diğer makaleleri için tıklayın.
İlgili etiketler: .net 3.5 CompiledQuery datacontext kod LINQ linq sorgusu Linq To Sql Performans Query test ADO.NET/SQL Oğuz Yağmur
 
YAZI HAKKINDA
Türü : Makale
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
Seviyesi : İleri
Kategori : ADO.NET/SQL
Yayınlanma Tarihi : 24.9.2009
Okunma Sayısı : 39001
Yorum Sayısı : 2     yorum yaz
Site İçi AramaSİTE İÇİ ARAMA
Üye Girişini AçÜye GİRİŞİ
Üye girişi için tıklayın.
Kullanıcı Adı
Şifre
 
Beni her zaman hatırla
Bir hafta boyunca kullanıcı bilgilerinizi kullanıcı çıkışı yapana kadar hatırlar. (Paylaşılan bilgisayarlarda önerilmez.)
 
Şifremi / Kullanıcı Adımı unuttum.
 
.net TV RSS Serbest KÖŞE (?)
Serbest Köşede C#nedir?com üyelerinin hazırladıkları yazılar yayınlanır. Bu yazılar editör incelemesine girmeden yayınlanır.
emre TAŞ
Silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
emre TAŞ
silindi
emre TAŞ
yazının devamı >
Makale Gönder Bende Yazmak İstiyorum
.net TV RSSBlogroll
Turhal Temizer
Conda install environment.yml Package 28.3.2024
Turhal Temizer
Mac OS/X Removing CUDA 28.3.2024
Burak Selim Şenyurt
Kurumsal Yazılımcının Oyun Geliştirme ile İmtihanı 28.3.2024
Burak Selim Şenyurt
Matematik ve Oyun Programlama - Missile Command - Final 28.3.2024
  Diğer Herşey
Sponsorlar
BT Akademi
Medya Portakal
Video Hosting Sponsoru
Csharpnedir.com bir Ineta üyesidir
Uzman Abi
Her Yönüyle C# - Sefer Algan
LinqToSql Kullanımında Performansı Artırmak (CompiledQuery)
 
Kapat
Sayfayı Yazdır Sık Kullanılanlara Ekle Arkadaşıma Gönder MySpace Del.Ico.Us Digg Facebook Google Mixx Reddit StumbleUpon

Microsoft Entity Framework’ü geliştirmeye devam etsin, birçok kimse çoktan Linq To Sql’i kullanmaya başladı ya da başlıyor. Linq To Sql öldü, diriliyor, iyi idi kötü idi, ORM midir değilmidir diye tartışılırken kullananların ilk sıkıntısı Linq To Sql’in performans sorunları oldu (Tüm ORM’lerin olduğu gibi). Linq To Sql ile geliştirme hızlı ve bir o kadar da kolay olmasına karşın sayıca çok ve kompleks tablolar üzerinde ağır sorgular yazılmaya başlandığında çalışan sorguların süre olarak zaman alması birçok kimsenin istemediği bir durum olmuştur. Bu yazımızda da bu sorun ile ilgili ne yapabileceğimizi inceleyeceğiz. Öncelikle kısa bir hatırlatma ile Linq To Sql’in aslında nasıl çalıştığını hatırlayalım. Böylelikle soruna hangi noktada müdahale edebileceğimizi daha net belirleyebiliriz.

Yukardaki şekilde de görüldüğü üzere, bir Linq To Sql sorgusu çalıştırılmak istendiğinde yazılan sorgu ifadesi her zaman söz dizimi(syntax) kontrolünden geçtikten sonra veritabanı sunucusuna özel bir şekilde SQL sorgusuna çevrilmektedir. Burdaki can sıkıcı nokta ise bu işlemin “her zaman” gerçekleşmedir. Örneğin bir müşteri verilerinin filitrelenmesi sırasında belirli kriterlere göre filitreleme yapılacağını düşünelim (ya da bir alışveriş sitesinde belirli bir markaya ait ürünleri listelemediğimizi de düşünebiliriz). Bu durumda her defasında veritabanı sunucusuna gönderilecek SQL sorgusunun oluşturulması için yazılan Linq To Sql sorgusunun yeniden sözdizimi kontrolü ve çevrim işlemlerinin yapılmasına ihtiyaç yoktur. Belki böyle bir sorun şu anda yaşamıyor olabiliriz ama bazen bu işlemlerin “her zaman” gerçekleşmesi önemli performans sorunlarına neden olabilmektedir.

Yukardaki kaba taslağa bakıldığında Linq To Sql yazımına müdahale edilemeyecektir.Özelleştirilmiş Linq To Sql motoru (Linq To X) yazılmadıkdan sonra çıkacak sonuca da (kısmen) müdahale edilemeyeceğine göre en azından “her zaman” gerçekleşen olayları devre dışı bırakabilirsek yani, Linq To Sql sorgusunun kontrol ve çevrim işlemlerinden sonraki oluşan sonucu global bir alanda saklayabilir (bir nevi önbellekleme –caching- yapılabilinirse)ve ihtiyaç duyulduğunda bu global alandan alıp kullanılırsa birçok iş devre dışı bırakılacağı için performans artışı sağlanılabilinir.



Linq To Sql sorgusu ilk defa işleme alındığındLinq To Sql sorgusu ilk defa işleme alındığında 1 ile numaralandırlmış okları takip ederek işlemlerden geçecektir. Bu işlemler sırasında Linq To Sql motoru ürettiği sonucu önbelleğe alacaktır. İkinci defa aynı yapıya sahip benzer bir Linq To Sql sorgusu işleme 2 ile numaralandırılmıs oklar takip edilecek yani önbellekden sonuç alınarak birçok işlem atlanılıp doğrudan veritabanına çalışması gereken SQL ifadesi gönderilecektir. Bu şekilde kazanılması düşünülen performans artımının ne ölçülerde olduğunu yukardaki bahsi geçen tekniği uygulamaya aldıkdan sonra test edeceğiz.

Daha önce de bahsedildiği gibi işlemlerden sonra oluşan sonucun saklanması ve tekrar kullanılması konusunda Linq To Sql kütüphanesi geliştiriciler için olanaklar sunuyor. System.Data.Linq isimalanı altındaki CompiledQuery isimli sealed sınıf sayesinde Linq To Sql sorgularını önbelleklenebilir.Oldukça basit bir yapıya sahip olan sınıfın geri dönüş değeri generic (şablon) bir delegate (temsilci) olan Compile isimli static ve üç farklı versiyonu bulunan (overloaded) metoda sahip (.NET Framework 3.5 gerekmektedir). Metodun geri dönüş değerinin bir temsilci olması istediğimiz kriterlere göre hazırlayacağımız metodun çağrılamasına olanak sağlamaktadır.

public static Func<TArg0, TArg1, TResult> Compile<TArg0, TArg1, TResult>(Expression<FuncTArg0, TArg1, TResult>> query) where TArg0 : DataContext;

Northwind veritabanı üzerindeki Products tablosundaki CategotyID’si 2 olan ürünleri listeleyecek bir örnek göz önüne alındığında Compile metodunun nasıl kullanılacağına bakalım.

İlk başta çok karışık gibi görünse de kısaca;
Targ0 DataContext nesnesini - zaten bu tip üzerine bir kısıtlayıcı (constraint) konulmuş -
Targ1 filitreleme işleminde kullanılacak parametreyi
TResult işlem sonucunda geriye dönecek verinin türünü
query ise Linq To Sql sorgusunu temsil etmektedir.

Northwind veritabanı üzerinde basit bir Linq To Sql sorgusu hazırlayarak nasıl kullanılacağını inceleyelim. Oncelikle derlenmiş sorgumuzu oluşturacak ifademizi hazırlayalım.

public static class BTADataOperations
{
    public static Func<nwDataContext, int, IQueryable<Product>> GetProductsByCatId = CompiledQuery.Compile((nwDataContext nwDc, int catId) =>
        from p in nwDc.Products
       where p.CategoryID == catId select p // bu ifade sonucu IQueryable türünden nesnedir!
    );
}

Compile metodunun geri dönüş değeri olan GetProductsByCatId temsilcisini kullanabilmek için DataContext nesnemizin bir örneğini ve ürüne ait kategori id’sini vermek yeterli olacaktır. Temsilcinin statik olması tüm uygulama içerisinden rahatça erişilebilmesini, uygulama boyunca tekil olmasını ve uygulama başlamadan önce hazır bir şekilde kullanıma hazır olmasını sağlamaktadır.

private void button1_Click(object sender, EventArgs e)
{
    nwDataContext dc = new nwDataContext();
    foreach( var p in BTADataOperations.GetProductsByCatId(dc, 2))
    {
        MessageBox.Show(p.ProductName);
    }
}

Yukardaki kod bloğu çalıştırıldığında kategori id’si 2 olan ürünlerin isimlerinin geldiği görülecektir. Test değerlendiemesine geçmeden önce GetProductsByCatId ile çalışmasını tasarladığımız Linq To Sql sorgusu birden fazla parametre alması durumunda ise şu şekilde bir çözüm geliştirilebilir.

public static class BTADataOperations
{
    public static Func<nwDataContext, ProductParameters, IQueryable<Product>> GetProducts= CompiledQuery.Compile((nwDataContext nwDc, ProductParameters parameters) =>
     from p in nwDc.Products
    where p.CategoryID == parameters.CatId && p.ProductName == parameters.ProductName
    select p );
}
public class ProductParameters
{
    public int CatId { get; set; }
    public string ProductName { get; set; }
    public int UnitsInStock { get; set; }
}

Daha öncede bahsedildiği gibi Compile metodunun ikinci parametresi Linq To Sql sorugusuna geçirilecek parametreyi temsil etmektedir. Aşağıdaki gibi birden fazla parametreyi ProductParameters türünden nesne oluşturup nesnenin özelliklerine değerlerini vererek Linq To Sql sorgusuna geçişi sağlanabilir.

nwDataContext dc = new nwDataContext();
foreach (var p in BTADataOperations.GetProducts(dc, new ProductParameters() { CatId=2, ProductName="Chef Anton's Cajun Seasoning" }))
{
    MessageBox.Show(p.ProductName);
}

Şimdi ise bu çalışmaların sonucunda ne kadar performans artışı sağlandığını inceleyelim. Bunun için aşağıdaki gibi bir yapılan işlemin süresini ölçen test kodu kullanılabilir. Ilk denemede tek bir sorgunun çalışmasını test edelim.

public Form1()
{
    InitializeComponent();
    var v = from s in dc.Products select s;
    foreach (var x in v)
        ;
}
Yukardaki kodun yazılmasının amacı DataContext nesnesinin her iki durum için kullanıma hazır hale gelmesini sağlamaktır. Aksi durumda DataContext nesnesinin ilk kullanımında birçok işlemin gerçekleşeceği için zaman almasından dolayı test sürelerinin yanlış çıkmasının önüne geçilmek istenmiştir.

Test Makinası :
.NET Framework 3.5 SP1
Visual Studio 2008 SP1
SQL Server 2005 SP2
Windows 7 RTM
3GB Bellek, 2.1 Ghz T8100 (32 bit) işlemci ve 300GB 7200RPM HDD

int times = 1;
nwDataContext dc = new nwDataContext();
private void button1_Click(object sender, EventArgs e)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < times; i++)
    {
         foreach (var p in BTADataOperations.GetProductsByCatId(dc, 2))
        { }
    }
    sw.Stop();
    MessageBox.Show(sw.ElapsedMilliseconds.ToString());
}
private void button2_Click(object sender, EventArgs e)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < times; i++)
    {
         foreach (var p in from product in dc.Products where product.CategoryID == 2 select product)
        { }
    }
    sw.Stop();
    MessageBox.Show(sw.ElapsedMilliseconds.ToString());
}

Sorgu Sayısı Complied Query Normal Query
1 0 ms 3 ms
10 3 ms 22 ms
100 30 ms 174 ms
1000 284 ms 1786 ms

Yukardaki sonuçlardan anlaşılacağı üzere CompiledQuery kullanarak hazırlanan Linq To Sql sorguları 5 – 6 kata kadar daha hızlı çalışmaktadır.Benzer yapıda Linq To Sql sorguların yoğun olarak kullanıldığı sistemlerde CompiledQuery sınıfının kullanılması performans açısından oldukça önem kazanmaktadır.


Örnek uygulamayı indimek için tıklayınız.

Makale:
LinqToSql Kullanımında Performansı Artırmak (CompiledQuery) ADO.NET ve SQL Oğuz Yağmur
  • Yazılan Yorumlar
  • Yorum Yaz
AĞU
6
2010
Sonuç etkileyici.
EKİ
7
2009
Böyle yeni teknolojilerde Türkçe kaynak bulmak gerçekten zor oluyor. Emeği geçen arkadaşa teşşekkür ederim.
Sayfalar : 1 
Yorum yazabilmek için üye girişi yapmalısınız. Üye girişi için tıklayın.
Üye değilseniz Üyel Ol linkine tıklayarak üyeliğinizi hemen başlatabilirisniz.
 
  • Bu Konuda Son 10
  • Eklenen Son 10
  • Bu Konuda Geçmiş 10
Bu Konuda Yazılmış Yazılmış 10 Makale Yükleniyor
Son Eklenen 10 Makale Yükleniyor
Bu Konuda Yazılmış Geçmiş Makaleler Yükleniyor