Lazy Loading vs Eager Loading: N+1 Problemi, Performans ve Production Best Practices

Bu rehberde Lazy Loading vs Eager Loading konusunu ileri seviyede ele alıyoruz. Özellikle Hibernate N+1 problemi, JOIN FETCH, EntityGraph ve production ortamında performans optimizasyonlarını öğreneceksiniz.

Kısa özet:
  • N+1 problemi = performans katili
  • Default: LAZY → Optimize ederek ilerle
  • JOIN FETCH & EntityGraph → kritik çözümler

N+1 Problemi Nedir?

N+1 problemi, Lazy Loading kullanılırken en sık karşılaşılan performans problemidir.

Örnek senaryo:

List<Order> orders = orderRepository.findAll();

for (Order order : orders) {
    System.out.println(order.getItems().size());
}

Bu durumda:

  • 1 adet ana sorgu (orders)
  • N adet alt sorgu (items)
Toplam sorgu: 1 + N → Bu ciddi performans problemidir.

Çözüm 1 — JOIN FETCH

En yaygın ve güçlü çözüm JOIN FETCH kullanmaktır.

@Query("SELECT o FROM Order o JOIN FETCH o.items")
List<Order> findAllWithItems();

Avantajları

  • Tek sorguda tüm veri çekilir
  • N+1 problemi ortadan kalkar

Dikkat Edilmesi Gerekenler

  • Pagination ile birlikte kullanımı zor olabilir
  • Çok fazla join performansı düşürebilir

Çözüm 2 — EntityGraph

Daha esnek ve temiz bir çözüm: EntityGraph

@EntityGraph(attributePaths = {"items"})
List<Order> findAll();

Avantajları

  • Declarative yapı (annotation bazlı)
  • Dinamik fetch kontrolü
  • Pagination ile uyumlu
JOIN FETCH yerine çoğu production projede EntityGraph tercih edilir.

Çözüm 3 — DTO Projection (En Temiz Yaklaşım)

En performanslı yöntem: sadece ihtiyaç duyulan veriyi çekmek

@Query("SELECT new com.app.dto.OrderDto(o.id, o.name) FROM Order o")
List<OrderDto> findOrders();

Neden Önemli?

  • Gereksiz veri çekilmez
  • Memory kullanımı azalır
  • En hızlı yöntemdir

Benchmark Senaryosu (Gerçekçi Yaklaşım)

10.000 kayıt üzerinden yapılan tipik karşılaştırma:

Yöntem Sorgu Sayısı Ortalama Süre
Lazy (N+1) 10001 1200 ms
JOIN FETCH 1 180 ms
EntityGraph 1 170 ms
DTO Projection 1 90 ms
En hızlı yöntem genellikle DTO projection’dır.

Production Best Practices 🚀

  • Default olarak LAZY kullan
  • EAGER kullanmaktan kaçın
  • N+1 problemini her zaman loglardan kontrol et
  • JOIN FETCH sadece gerektiğinde kullan
  • EntityGraph ile esnek yapı kur
  • DTO projection ile minimum veri çek
  • Pagination + fetch kombinasyonuna dikkat et
En büyük hata: Her ilişkiyi EAGER yapmak → Production’da sistem çökertir.

Sonuç

Lazy vs Eager tartışması tek başına yeterli değildir. Asıl önemli olan:

  • N+1 problemini yönetmek
  • Doğru fetch stratejisini seçmek
  • Gerçek kullanım senaryosuna göre optimize etmektir

Modern uygulamalarda en doğru yaklaşım: LAZY + DTO + gerektiğinde optimize

Etiketler: hibernate n+1, join fetch, entitygraph, jpa performance, lazy loading optimization, eager loading problem

Latest Software Developers - Yazılım Blog Yazarı Profil Resmi

Yazar

LatestSoftwareDevelopers

Güncel yazılım teknolojilerinin takip edildiği blog.

Java ile ilgili yorumlar

Yorum Paylaş

EMail Zorunlu alanlar * *