Merhaba arkadaşlar, bugün Laravel'de performansı en çok düşüren ve benim de başımı defalarca ağrıtan o meşhur N+1 sorgu problemini nasıl tespit edip çözdüğümden bahsedeceğim. Bu hatayı ilk gördüğümde, sayfa basit görünüyordu ama veritabanı sunucusu adeta kükrüyordu. İşte benim kullandığım en temiz çözüm yolları.
N+1 Problemi Nedir ve Neden Kafayı Yedirir?
Basitçe anlatmak gerekirse, bir liste içindeki her bir kayıt için ayrı ayrı ek sorgular çalıştırıyorsanız N+1 problemi yaşıyorsunuz demektir. Örneğin, 100 blog yazısı (`Post`) çekip, her birinin yazar bilgisini (`User`) ayrı bir sorguyla almak. Bu, 1 ana sorgu + 100 ek sorgu demek! Performans katili.
Debug Toolbar ile Görünmez Düşmanı Görmek
Sorunu çözmenin ilk adımı, onu görmektir. Laravel ekosisteminde bu iş için biçilmiş kaftan Laravel Debugbar. Paketi kurduktan sonra, tarayıcınızın altında/kenarında açılan paneldeki Queries sekmesi sizi aydınlatacak.
Orada, aynı türden onlarca sorgunun arka arkaya çalıştığını göreceksiniz. İşte o an, "Eyvah!" diyeceksiniz. Debugbar olmadan bu sorunu fark etmek, özellikle lokal ortamda hızlı çalışan bir veritabanınız varsa, çok zor.
Çözüm 1: Eager Loading (with() ile İlişkileri Önceden Yükle)
Laravel'in bu soruna birinci ve en temel çözümü `with()` metodudur. İlişkili modelleri ana sorguya dahil ederek tek bir sorguda getirir.
Debugbar'ı açıp iki kodu karşılaştırın. Sorgu sayısındaki dramatik düşüş sizi mutlu edecek.
Çözüm 2: İhtiyaca Özel Eager Loading (withCount, withAvg, vs.)
Bazen tüm ilişkili modeli değil, sadece bir sayısını veya ortalamasını almak istersiniz. Bu durumda bile ayrı sorgular çalışabilir. Laravel'in `withCount()` gibi sihirli metodları imdada yetişir.
Son Söz ve Debugbar Alışkanlığı
Artık her yeni bir Laravel projesine başladığımda, geliştirme ortamına ilk kurduğum paketlerden biri Debugbar oluyor. Sadece N+1 için değil, yavaş sorguları, bellekte nelerin tutulduğunu, view'ların render süresini izlemek için de paha biçilmez bir araç.
Siz de Laravel'de N+1 tuzağına düştünüz mü? Yoksa sizin başka bir debug veya performans izleme taktiğiniz var mı? Yorumlarda paylaşalım, hep birlikte öğrenelim.
Basitçe anlatmak gerekirse, bir liste içindeki her bir kayıt için ayrı ayrı ek sorgular çalıştırıyorsanız N+1 problemi yaşıyorsunuz demektir. Örneğin, 100 blog yazısı (`Post`) çekip, her birinin yazar bilgisini (`User`) ayrı bir sorguyla almak. Bu, 1 ana sorgu + 100 ek sorgu demek! Performans katili.
Sorunu çözmenin ilk adımı, onu görmektir. Laravel ekosisteminde bu iş için biçilmiş kaftan Laravel Debugbar. Paketi kurduktan sonra, tarayıcınızın altında/kenarında açılan paneldeki Queries sekmesi sizi aydınlatacak.
Orada, aynı türden onlarca sorgunun arka arkaya çalıştığını göreceksiniz. İşte o an, "Eyvah!" diyeceksiniz. Debugbar olmadan bu sorunu fark etmek, özellikle lokal ortamda hızlı çalışan bir veritabanınız varsa, çok zor.
Laravel'in bu soruna birinci ve en temel çözümü `with()` metodudur. İlişkili modelleri ana sorguya dahil ederek tek bir sorguda getirir.
PHP:
// PROBLEMLİ KOD (N+1):
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name; // Her döngüde yeni bir sorgu!
}
// ÇÖZÜM (Eager Loading):
$posts = Post::with('author')->get(); // Sadece 2 sorgu!
foreach ($posts as $post) {
echo $post->author->name; // Sorgu yok, veri hazır!
}
Debugbar'ı açıp iki kodu karşılaştırın. Sorgu sayısındaki dramatik düşüş sizi mutlu edecek.
Bazen tüm ilişkili modeli değil, sadece bir sayısını veya ortalamasını almak istersiniz. Bu durumda bile ayrı sorgular çalışabilir. Laravel'in `withCount()` gibi sihirli metodları imdada yetişir.
PHP:
// Her bir post için ayrı ayrı yorum sayısı sorgusu ÇALIŞMASIN!
$posts = Post::withCount('comments')->get();
foreach ($posts as $post) {
echo $post->title . " (" . $post->comments_count . " yorum)";
}
// Hatta birden fazla ilişkiyi ve istatistiği tek seferde...
$posts = Post::with(['author', 'tags'])->withCount('comments')->withAvg('ratings', 'score')->get();
Artık her yeni bir Laravel projesine başladığımda, geliştirme ortamına ilk kurduğum paketlerden biri Debugbar oluyor. Sadece N+1 için değil, yavaş sorguları, bellekte nelerin tutulduğunu, view'ların render süresini izlemek için de paha biçilmez bir araç.
Siz de Laravel'de N+1 tuzağına düştünüz mü? Yoksa sizin başka bir debug veya performans izleme taktiğiniz var mı? Yorumlarda paylaşalım, hep birlikte öğrenelim.