Veritabanı N+1 Sorgusu: Eager Loading ve Lazy Loading Tuzakları

N+1 sorgusu, bir ana tablodan veri çekerken her satır için ek bir sorgu çalıştırılan performans sorunudur. Mesela 100 kullanıcıyı çektikten sonra her kullanıcının siparişlerini ayrı ayrı sorgulamak 1 + 100 = 101 sorgu demektir.

Lazy loading (tembel yükleme) kullandığında, ilişkili veriye erişilene kadar sorgu yapılmaz. Döngü içinde bu erişim tekrarlanırsa her iterasyonda yeni bir sorgu tetiklenir. Örnek olarak bir blog uygulamasında yazarlar ve yazıları düşün:

1# Yazarlar çekiliyor (1 sorgu)
2authors = Author.all()
3
4# Her yazarın yazılarını çekme (N sorgu)
5for author in authors:
6posts = author.posts # Her döngüde 1 sorgu!
7for post in posts:
8print(post.title)

Bu kod N+1 sorununa neden olur. İlk sorgu yazarları, sonra her yazar için ayrı sorgu yapılır.

Eager loading (istekli yükleme), ilişkili verileri baştan yükler. Veritabanı birleşimi (JOIN) kullanarak tek sorguya indirir:

Reklam · TEST
AdSense Test ReklamıYazı arası (gönderi içi) · Yazı arası
1# Yazarlar ve yazılarını bir sorguyla çekme
2authors = Author.includes(:posts)
3
4# Hiç yeni sorgu yapılmaz
5for author in authors:
6for post in author.posts:
7print(post.title)

Bu durumda 2 sorgu yapılır: biri yazarlar, biri yazılar (JOIN ile). Yazılar bellekte ilişkilendirilir.

Lazy loading her zaman kötü değildir. Eğer yazarları çekip yalnızca isimlerini göstermek istiyorsan, yazıları yüklemeye gerek yok. Sadece gerekli veriye erişildiğinde yüklenir, bellek tasarrufu sağlar.

Eager loading kullanırken fazla ilişki yüklemek de sorun yaratır. Mesela yazarların tüm yorumlarını, yorumların tüm beğenilerini yüklemek gereksiz bellek tüketir. İhtiyaca göre seç:

1# Sadece yazıları yükle
2authors = Author.includes(:posts)
3
4# Yazıları ve her yazının yorumlarını yükle
5authors = Author.includes(posts::comments)

N+1 sorgusu genellikle geliştirme sırasında fark edilmez ama canlı ortamda binlerce sorgu çalıştırabilir. Veritabanı log'larını kontrol etmek ve test sırasında sorgu sayısını ölçmek alışkanlık haline getir.

Reklam · TEST
AdSense Test ReklamıGönderi altı · Görüntülü
konu hakkında tepkinizi verebilirsiniz