Menghindari Query N+1 pada Daftar Artikel Laravel
Muat penulis bersama daftar artikel dengan eager loading dan pilih kolom relasi dengan benar.
Daftar artikel sering menampilkan nama penulis pada setiap baris. Jika relasi dimuat satu per satu saat template dibaca, jumlah query dapat meningkat mengikuti jumlah artikel. Pola tersebut dikenal sebagai N+1.
Contoh ini mengasumsikan posts.user_id menunjuk ke users.id. Definisikan relasi bernama author pada model Post, lalu muat relasi sebelum data diteruskan ke Blade. Query utama tetap menyertakan foreign key yang dibutuhkan untuk memasangkan penulis.
Contoh implementasi
// In App\Models\Post:
public function author(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(\App\Models\User::class, 'user_id');
}
// In the controller:
$posts = \App\Models\Post::query()
->select(['id', 'user_id', 'title'])
->with('author:id,name')
->orderByDesc('id')
->limit(20)
->get();
return view('articles.index', compact('posts'));
@foreach ($posts as $post)
<article>
<h2>{{ $post->title }}</h2>
<p>{{ $post->author?->name ?? 'Unknown author' }}</p>
</article>
@endforeach
Cara memeriksa
Bandingkan query di lingkungan pengembangan sebelum dan setelah menambahkan with. Untuk kumpulan yang tidak kosong, pengambilan artikel dan penulis pada contoh membutuhkan dua query utama, bukan satu query penulis per baris. Query lain dari sesi atau middleware tetap mungkin muncul.
Jangan menghapus user_id dari pilihan kolom Post atau id dari pilihan kolom User. Keduanya diperlukan untuk pencocokan relasi. Sebagai latihan, tambahkan jumlah komentar dengan withCount('comments') setelah relasi komentar tersedia, lalu periksa query kembali.
