Tekrardan merhabalar, eskiden yaptığım bir projede bir baktım ki ne göreyim, sayfaya girince her bir kayıt için tekrar tekrar veritabanına istek göndermişim. Halbuki 2-3 sorguda halledebileceğim bir şeyi 50 sorguda yaptırmışım.
İlk olarak Eager Load nedir buna bir bakalım. Diyelim ki 3 adet Modelimiz olsun. User, Image ve Meta adında olsun. İlişkisi sırası ise User > Image > Meta olsun. Diyelim ki 50 tane User var ve bunların her birinin Image modelinde resimleri var. O halde User modelinden Image modeline hasMany ilişkisi vereceğiz.
// User.php Model
public function images(){
return $this->hasMany(Image:class);
}
Normal olarak her üyenin resimlerini alacağımız yapıda şöyle olmalı.
$users = User::all();
foreach($users as $user){
$images = $user->images;
...
}
Ancak burada 50 adet User olur ise her döngüde tekrar tekrar images tablosuna gitmek zorunda kalacak. Bu userların hepsinin resimlerini tek sorguda veritabanından nasıl alabiliriz? Cevap eager load. Bu yapı sayesinde elimizde var olan userlar için 1 sorgu daha gönderiliyor ve sql deki “IN” komutuyla bu userlara ait resimleri bize veriyor.
Eagler load kullanmak için Eloquent üzerine ->with(“relationship_adi”); yazmamız gerekiyor. Bizim örneğimizde ise.
$users = User::with("images")->all(); // images ler ile birlikte.
foreach($users as $user){
$images = $user->images;
...
}
Bu döngüde ise sadece 2 sorgu çalıştı. İlk sorgu üyeleri çekmek içindi, ikincisi ise bu üyelerin resimlerini çekmek içindi. Peki önceki yapıda ne oluyordu? İlk sorgu üyeleri çekiyor ondan sonra gelen 50 sorgu ise bu üyelerin her biri için resimlerini çekiyordu.
Tabi ki burada çok fazla user olursa ve her userin çok fazla resmi olur ise, birde eager load ile bunları almak istersek ne olacak? Tabiki bütün veriler memoryde olacağı için RAM şişecek 🙂 Bunu engellemek için ise chunk yöntemi kullanılabilir ama bu başka bir makale konusu 🙂
Asıl konumuza dönersek, diyelim ki bu Image modelinin de metas adında başka bir ilişkisi daha var ve döngü içerisinde onlara da ulaşmamız gerekiyor.
// Image.php Model
public function metas(){
return $this->hasMany(Meta::class);
}
$users = User::with("images")->all(); // images ler ile birlikte.
foreach($users as $user){
$images = $user->images;
$metas = $user->metas;
...
}
User içinde Image için bir ilişki yaptık ve images ları tek sorguda aldık. Ee peki bu Image in içindeki metaları nasıl alacağız? Yukardaki gibi yaparsak yine her döngüde imagein metaslarını almak için sorgu gönderecek. Laraveli yapan bu çok zeki abilerimiz şöyle bir yapı kurmuşlar 🙂
$users = User::with("images.metas")->all(); // images.metas
foreach($users as $user){
$images = $user->images;
$metas = $user->metas;
...
}
İşte bu yapıda ise sadece 3 sorgu çalışıyor. İlki usersları alıyor, ikincisi bu userlerin imageslarını alıyor, 3. sorgu ise bu imagesların metaslarını alıyor 🙂 Bu sayede veritabanını fazla yormadan verilerimize erişebildik 🙂
Eğer bu işlemlerde hangi sql sorguları çalışıyor görmek isterseniz, daha önce yazmış olduğum bu konuda Laravel Debugbar eklentisini kurarak görebilirsiniz.
İlk Yorumu Siz Yapın