Skip to main content
Yazılım Geliştirme

Entity Framework Core: Performans Optimizasyonu

Mart 06, 2026 6 dk okuma 21 views Raw
Ayrıca mevcut: en
Entity Framework Core performans optimizasyonu - veritabanı ve sunucu ortamı
İçindekiler

Entity Framework Core Neden Performans Optimizasyonuna İhtiyaç Duyar?

Entity Framework Core, .NET ekosisteminin en popüler ORM (Object-Relational Mapping) aracıdır. Geliştiricilere veritabanı işlemlerini nesne yönelimli bir yaklaşımla yönetme imkanı sunar. Ancak bu kolaylık, dikkatli kullanılmadığında ciddi performans sorunlarına yol açabilir. Özellikle büyük ölçekli uygulamalarda, EF Core'un varsayılan davranışları yeterli olmayabilir ve uygulamanızın yanıt sürelerini olumsuz etkileyebilir.

Performans optimizasyonu, sadece sorguların hızlandırılması anlamına gelmez. Bellek tüketiminin azaltılması, veritabanı bağlantılarının verimli kullanılması ve uygulamanın ölçeklenebilirliğinin artırılması da bu sürecin önemli parçalarıdır. Bu rehberde, EF Core projelerinizde uygulayabileceğiniz kanıtlanmış optimizasyon tekniklerini ele alacağız.

N+1 Sorgu Problemi ve Çözümü

N+1 problemi, EF Core ile çalışırken karşılaşılan en yaygın performans sorunlarından biridir. Bu problem, bir ana sorgudan sonra ilişkili her kayıt için ayrı bir sorgu çalıştırılması durumunda ortaya çıkar. Örneğin, 100 siparişi ve her siparişin müşteri bilgisini çekmek istediğinizde, 1 ana sorgu artı 100 ek sorgu yapılır.

Eager Loading ile Çözüm

Include ve ThenInclude metotlarını kullanarak ilişkili verileri tek bir sorguda yükleyebilirsiniz. Bu yaklaşım, veritabanına yapılan istek sayısını dramatik biçimde azaltır.

var orders = await context.Orders
    .Include(o => o.Customer)
    .Include(o => o.OrderItems)
        .ThenInclude(oi => oi.Product)
    .ToListAsync();

Explicit Loading Kullanımı

Bazı durumlarda tüm ilişkili verileri eager loading ile yüklemek gereksiz olabilir. Explicit loading, belirli koşullara bağlı olarak ilişkili verileri yüklemenize olanak tanır. Bu yöntem, yalnızca ihtiyaç duyulan verilerin yüklenmesini sağlayarak bellek kullanımını optimize eder.

AsNoTracking ile Sorgu Performansını Artırma

EF Core, varsayılan olarak sorgu sonuçlarını change tracker üzerinden izler. Bu izleme mekanizması, varlıklar üzerinde yapılan değişikliklerin otomatik olarak algılanmasını sağlar. Ancak salt okunur sorgularda bu izleme gereksiz bir yük oluşturur.

AsNoTracking metodu, sorgu sonuçlarının change tracker'a eklenmesini engeller. Bu, özellikle raporlama sayfaları, listeleme ekranları ve API endpoint'leri gibi veri değişikliği yapılmayan senaryolarda önemli performans kazanımı sağlar.

var products = await context.Products
    .AsNoTracking()
    .Where(p => p.IsActive)
    .ToListAsync();

Büyük veri setlerinde AsNoTracking kullanımı, bellek tüketimini yüzde elliye kadar azaltabilir ve sorgu süresini önemli ölçüde kısaltabilir. Eğer uygulamanızda çoğu sorgu salt okunur ise, DbContext seviyesinde varsayılan olarak tracking'i kapatmayı düşünebilirsiniz.

Projection ve Select ile Veri Miktarını Azaltma

Veritabanından tüm sütunları çekmek yerine, yalnızca ihtiyaç duyulan alanları seçmek önemli bir optimizasyon tekniğidir. Select ifadesi kullanarak projection yapabilir ve ağ üzerinden taşınan veri miktarını minimuma indirebilirsiniz.

var productList = await context.Products
    .Where(p => p.IsActive)
    .Select(p => new ProductDto
    {
        Id = p.Id,
        Name = p.Name,
        Price = p.Price
    })
    .ToListAsync();

Bu yaklaşım, özellikle çok sayıda sütuna sahip tablolarda dramatik performans iyileştirmesi sağlar. Ayrıca projection kullanıldığında EF Core otomatik olarak tracking'i devre dışı bırakır, bu da ek bir performans avantajı sunar.

Compiled Query Kullanımı

Sık çalıştırılan sorgular için compiled query kullanmak, sorgu derleme maliyetini ortadan kaldırır. EF Core, her sorgu çalıştırıldığında LINQ ifadesini SQL'e çevirir. Compiled query ile bu çeviri yalnızca bir kez yapılır ve sonraki çağrılarda önbellekten kullanılır.

private static readonly Func<AppDbContext, int, Task<Product>> GetProductById =
    EF.CompileAsyncQuery((AppDbContext context, int id) =>
        context.Products.FirstOrDefault(p => p.Id == id));

Compiled query, yüksek trafikli uygulamalarda sorgu derleme süresini sıfıra indirerek yanıt sürelerini iyileştirir. Özellikle saniyede yüzlerce kez çalıştırılan sorgularda bu fark belirgin hale gelir.

Batch İşlemleri ve ExecuteUpdate/ExecuteDelete

EF Core 7 ve sonrası sürümlerde tanıtılan ExecuteUpdate ve ExecuteDelete metotları, toplu güncelleme ve silme işlemlerini tek bir SQL komutuyla gerçekleştirmenize olanak tanır. Geleneksel yöntemde her kayıt için ayrı bir UPDATE veya DELETE komutu gönderilirken, bu metotlar tek bir komutla tüm işlemi tamamlar.

await context.Products
    .Where(p => p.Stock == 0)
    .ExecuteDeleteAsync();

await context.Products
    .Where(p => p.CategoryId == categoryId)
    .ExecuteUpdateAsync(s => s
        .SetProperty(p => p.IsActive, false)
        .SetProperty(p => p.UpdatedAt, DateTime.UtcNow));

Bu yaklaşım, binlerce kaydı etkileyen işlemlerde performansı onlarca kat artırabilir. Verilerin belleğe yüklenmesine gerek kalmadan doğrudan veritabanında işlem yapılması, hem hız hem de bellek açısından büyük avantaj sağlar.

Veritabanı İndeksleme Stratejileri

Doğru indeksleme, veritabanı performansının temel taşıdır. EF Core ile Fluent API veya Data Annotations kullanarak indeksler tanımlayabilirsiniz. Sık sorgulanan sütunlara indeks eklemek, sorgu sürelerini önemli ölçüde kısaltır.

Composite Index Kullanımı

Birden fazla sütun üzerinde filtreleme yapılan sorgularda composite index kullanmak etkili bir yöntemdir. Sütun sıralaması, sorgu performansını doğrudan etkiler; en seçici sütun ilk sıraya yerleştirilmelidir.

Filtered Index

Belirli koşullara sahip kayıtları sık sorguluyorsanız, filtered index kullanarak indeks boyutunu küçültebilir ve performansı artırabilirsiniz. Örneğin, yalnızca aktif ürünler üzerinde bir indeks oluşturmak, o sorgu için çok daha verimli olacaktır.

Connection Pooling ve DbContext Yönetimi

DbContext nesnesinin yaşam döngüsü, uygulama performansını doğrudan etkiler. DbContext, kısa ömürlü olacak şekilde tasarlanmıştır ve her istek için yeni bir instance oluşturulmalıdır. ASP.NET Core'da dependency injection ile AddDbContext kullanıldığında bu yönetim otomatik olarak sağlanır.

Connection pooling, veritabanı bağlantılarının yeniden kullanılmasını sağlayarak bağlantı kurma maliyetini azaltır. EF Core, varsayılan olarak ADO.NET connection pooling mekanizmasını kullanır. Ancak DbContext pooling özelliğini etkinleştirerek ek performans kazanımı elde edebilirsiniz.

builder.Services.AddDbContextPool<AppDbContext>(options =>
    options.UseSqlServer(connectionString), poolSize: 128);

DbContext pooling, özellikle yüksek eşzamanlılık gerektiren uygulamalarda bağlantı yönetimi yükünü azaltır ve yanıt sürelerini iyileştirir.

Sayfalama ve Veri Limitleme

Büyük veri setlerini tek seferde yüklemek hem bellek hem de ağ performansını olumsuz etkiler. Skip ve Take metotlarını kullanarak sunucu taraflı sayfalama uygulamak, performansın korunması için kritik öneme sahiptir.

var pagedProducts = await context.Products
    .OrderBy(p => p.Name)
    .Skip((pageNumber - 1) * pageSize)
    .Take(pageSize)
    .ToListAsync();

Keyset pagination (seek yöntemi) kullanmak, büyük veri setlerinde OFFSET tabanlı sayfalamaya göre çok daha performanslıdır. Bu yöntemde son kaydın değeri bir sonraki sayfa için filtre olarak kullanılır ve veritabanı gereksiz kayıtları atlamak zorunda kalmaz.

Raw SQL ve Stored Procedure Kullanımı

EF Core'un LINQ sağlayıcısı çoğu senaryoda yeterli olsa da, karmaşık sorgularda veya performans kritik noktalarda raw SQL kullanmak gerekebilir. FromSqlRaw ve FromSqlInterpolated metotları, doğrudan SQL komutları çalıştırmanıza olanak tanır.

Stored procedure'ler, karmaşık iş mantığını veritabanı tarafında çalıştırarak ağ trafiğini azaltır. Özellikle raporlama ve veri dönüşüm işlemlerinde stored procedure kullanımı önemli performans avantajı sağlar.

Performans optimizasyonu bir kerelik bir işlem değil, sürekli bir süreçtir. Uygulamanızın büyümesiyle birlikte optimizasyon stratejilerinizi de güncellemeniz gerekir.

İkinci Seviye Önbellekleme

EF Core, birinci seviye önbellekleme olarak change tracker'ı kullanır. Ancak sık erişilen ve nadir değişen veriler için ikinci seviye önbellekleme uygulamak büyük fayda sağlar. Üçüncü parti kütüphaneler veya IMemoryCache ve IDistributedCache arayüzleri kullanılarak bu mekanizma kurulabilir.

Önbellekleme stratejisi belirlerken verinin ne sıklıkta değiştiğini, tutarsızlık toleransını ve bellek kısıtlarını göz önünde bulundurmalısınız. Cache invalidation politikası doğru belirlenmezse, kullanıcılara eski veriler sunulabilir.

Performans İzleme ve Profiling

Optimizasyon yapmadan önce darboğazları tespit etmek gerekir. EF Core, sorgu loglaması için zengin altyapı sunar. Geliştirme ortamında SQL sorgularını loglamak, beklenmedik sorgu desenlerini tespit etmenize yardımcı olur.

  • EF Core logging altyapısını etkinleştirerek oluşturulan SQL sorgularını inceleyin
  • MiniProfiler veya benzeri araçlarla sorgu sürelerini ölçün
  • Application Insights veya benzeri APM araçlarıyla üretim ortamını izleyin
  • Database query plan analyzer ile sorgu planlarını analiz edin
  • Slow query log'larını düzenli olarak gözden geçirin

Özet ve En İyi Uygulamalar

Entity Framework Core performans optimizasyonu, katmanlı bir yaklaşım gerektirir. Aşağıdaki kontrol listesi, projelerinizde uygulayabileceğiniz temel optimizasyon adımlarını özetler.

  1. Salt okunur sorgularda AsNoTracking kullanın
  2. İlişkili verileri Include ile eager loading yaparak N+1 probleminden kaçının
  3. Select ile projection yaparak yalnızca gerekli alanları çekin
  4. Toplu işlemlerde ExecuteUpdate ve ExecuteDelete kullanın
  5. Sık çalıştırılan sorgular için compiled query tanımlayın
  6. Doğru indeksleme stratejisi belirleyin
  7. DbContext pooling kullanarak bağlantı yönetimini optimize edin
  8. Sunucu taraflı sayfalama uygulayın
  9. Gerektiğinde raw SQL veya stored procedure kullanmaktan çekinmeyin
  10. Performans izleme araçlarıyla sürekli ölçüm yapın

Bu teknikleri sistematik olarak uygulayarak EF Core tabanlı uygulamalarınızın performansını önemli ölçüde artırabilirsiniz. Her optimizasyonun etkisini ölçerek, uygulamanız için en değerli iyileştirmelere odaklanmanız kritik önem taşır.

Bu yazıyı paylaş