İçeriğe geç

Kısa Bilgi 11 – Lazy Loading vs Eager Loading

Entity Framework aracılığı ile veri erişim noktasında 2 farklı yapıyı inceleyebiliriz. Bunlar Lazy Loading ve Eager Loading. Bunlar üzerinden bir performans karşılaştırması yaptığımda aşağıdaki sonuçlara ulaştım.

 

Senaryo gereği AdventureWorksLT2008 isimli veritabanımız üzerinden ProductCategory tablosundan kategori isimlerini yazdıralım ve bu kategorilerde kaç kayıt olduğunu gösterelim. Öncelikle Lazy Loading kullanarak kayıtlara direk erişim yapalım ve sonrasında kendimiz include edelim. Sonra aralarındaki işlemlerin tamamlama sürelerini karşılaştıralım.

Lazy Loading

 private static void GetProductInfoWithoutInclude()
 {
 AdventureWorksLT2008Entities db = new AdventureWorksLT2008Entities();
 var categories = db.ProductCategory
 .ToList();

 categories.ForEach(p =>
 {
 Console.WriteLine(string.Format("{0} [{1}]", p.Name, p.Product.Count));
 });
 }

Eager Loading

 private static void GetProductInfoWithInclude()
 {
 AdventureWorksLT2008Entities db = new AdventureWorksLT2008Entities();

 db.Configuration.LazyLoadingEnabled = false;
 var categories = db.ProductCategory
 .Include("Product")
 .ToList();

 categories.ForEach(p =>
 {
 Console.WriteLine(string.Format("{0} [{1}]", p.Name, p.Product.Count));
 });
 }

Bu 2 yaklaşım üzerinden 5 farklı deneme yaptığımda sonuçlar aşağıdaki gibi oldu.

Lazy Loading EagerLoading
1.123 0.623
1.073 0.897
1.124 0.615
1.022 0.565
1.051 0.693

Burada bariz şekilde Lazy Loading kullanım sıkıntısı görünmekte. Bunun sebebi eğer SQL Server Profiler ile inceleme yaparsanız göreceksiniz. Arka planda count çekmek amacıyla çok fazla sorgu dönmektedir. Örnek bir count sorgusunun çıktısı şöyle:

exec sp_exe<>>>>cutesql N'SELECT 
    [Extent1].[ProductID] AS [ProductID], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[ProductNumber] AS [ProductNumber], 
    [Extent1].[Color] AS [Color], 
    [Extent1].[StandardCost] AS [StandardCost], 
    [Extent1].[ListPrice] AS [ListPrice], 
    [Extent1].[Size] AS [Size], 
    [Extent1].[Weight] AS [Weight], 
    [Extent1].[ProductCategoryID] AS [ProductCategoryID], 
    [Extent1].[ProductModelID] AS [ProductModelID], 
    [Extent1].[SellStartDate] AS [SellStartDate], 
    [Extent1].[SellEndDate] AS [SellEndDate], 
    [Extent1].[DiscontinuedDate] AS [DiscontinuedDate], 
    [Extent1].[ThumbNailPhoto] AS [ThumbNailPhoto], 
    [Extent1].[ThumbnailPhotoFileName] AS [ThumbnailPhotoFileName], 
    [Extent1].[rowguid] AS [rowguid], 
    [Extent1].[ModifiedDate] AS [ModifiedDate]
    FROM [SalesLT].[Product] AS [Extent1]
    WHERE [Extent1].[ProductCategoryID] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=39

Not: Eğer Linq kullanımını bu şekilde yaparsanız buradaki senaryoya göre gereksiz kolonlar için de veri erişimi yapmış oluyoruz. Bunun yerine anonymous type kullanımı daha uygun olacaktır. Böyle bir durumda Lazy Loading kullanımı ile include işlemi otomatik yapılmış oluyor.

AdventureWorksLT2008Entities db = new AdventureWorksLT2008Entities();
var categories = db.ProductCategory
.Select(p => new { p.Name, p.Product }) // anonymous type
.ToList();

categories.ForEach(p =>;
{
Console.WriteLine(string.Format("{0} [{1}]", p.Name, p.Product.Count));
});

Projeye ait dosyayı şu linkten indirebilirsiniz. Veritabanını içine eklemiyorum zira boyutu artıyor 🙂

Tarih:Kısa Bilgi

İlk Yorumu Siz Yapın

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

This site uses Akismet to reduce spam. Learn how your comment data is processed.