KodeJs
Cara Mengatasi N+1 Query Problem di Laravel 13 (Eager Loading)
Laravel3 menit baca

Cara Mengatasi N+1 Query Problem di Laravel 13 (Eager Loading)

Kembali ke Blog
Egi Samsul Mu'arifEgi Samsul Mu'arif5 September 20263 menit baca

Tutorial mengatasi N+1 query problem di Laravel 13 menggunakan Eager Loading. Buat performa database aplikasi web kamu jauh lebih cepat!

Aplikasi web yang terasa lambat saat memuat halaman daftar data (list view) sering kali bukan disebabkan oleh spesifikasi server yang rendah, melainkan karena masalah efisiensi kueri database yang dikenal sebagai N+1 Query Problem.

Di Laravel 13, masalah ini kerap terjadi secara tidak disadari saat kita menggunakan fitur Lazy Loading pada relasi Eloquent.

Artikel ini akan mengulas apa itu N+1 Query Problem, dampaknya pada performa aplikasi, dan cara mengatasinya secara instan menggunakan Eager Loading.

Memahami N+1 Query Problem

Masalah N+1 Query terjadi ketika aplikasi melakukan 1 kueri utama untuk mengambil data induk (parent), lalu menjalankan N kueri tambahan di dalam perulangan (loop) untuk mengambil data anak (child) dari setiap baris data induk tersebut.

Contoh Kasus (Lazy Loading):

Bayangkan kamu memiliki 100 data Product, dan setiap produk terhubung ke satu Category.

PHP

// 1. Kueri Pertama: Mengambil 100 produk
$products = Product::all(); 

foreach ($products as $product) {
    // 2. Kueri Tambahan: Dijalankan 100 KALI di dalam loop!
    echo $product->category->name; 
}

Total kueri yang dieksekusi:

$$1 \text{ (kueri induk)} + 100 \text{ (kueri perulangan)} = 101 \text{ Kueri SQL}$$

Jika data produk berkembang menjadi 1.000 item, Laravel akan menjalankan 1.001 kueri ke database hanya untuk menampilkan satu halaman web! Hal inilah yang membuat response time server membengkak drastis.

┌─────────────────────────────────────────────────────────────────────────┐
│                    PERBANDINGAN LAZY VS EAGER LOADING                   │
├────────────────────────────────┬────────────────────────────────────────┤
│ Lazy Loading (N+1 Problem)     │ Eager Loading (Optimized)              │
├────────────────────────────────┼────────────────────────────────────────┤
│ • Exec: `Product::all()`       │ • Exec: `Product::with('category')->get()`│
│ • Total Kueri: 1 + N (Banyak)  │ • Total Kueri: Selalu 2 Kueri          │
│ • Beban Database: Sangat Berat │ • Beban Database: Sangat Ringan        │
└────────────────────────────────┴────────────────────────────────────────┘

Solusi: Menggunakan Eager Loading with()

Untuk mengatasi masalah ini, kita menggunakan teknik Eager Loading melalui metode with().

Metode ini menginstruksikan Eloquent untuk mengambil data induk beserta semua data relasinya di awal secara sekaligus menggunakan kueri SQL WHERE IN.

PHP

// Hanya menjalankan 2 Kueri SQL!
$products = Product::with('category')->get();

foreach ($products as $product) {
    // Tidak ada kueri tambahan yang dijalankan di sini
    echo $product->category->name; 
}

Kueri SQL yang Dijalankan di Belakang Layar:

  1. SELECT * FROM products;

  2. SELECT * FROM categories WHERE id IN (1, 2, 3, 4, ...);

Dengan teknik ini, tidak peduli berapa pun jumlah data produknya (100 maupun 10.000 data), kueri yang dieksekusi tetap berjumlah 2 kueri saja.

1. Eager Loading Banyak Relasi (Multiple Relations)

Jika sebuah model memiliki beberapa relasi sekaligus, kamu bisa memasukkannya dalam bentuk array:

PHP

$products = Product::with(['category', 'brand', 'supplier'])->get();

2. Nested Eager Loading (Relasi Bertingkat)

Kamu juga dapat mengambil data relasi bersarang (nested relationship) menggunakan notasi titik (.):

PHP

// Mengambil Product -> Category -> Department
$products = Product::with('category.department')->get();

3. Lazy Eager Loading load()

Jika objek model sudah terlanjur di-load di bagian awal kode, kamu bisa menerapkan Eager Loading secara susulan menggunakan method load():

PHP

$products = Product::all();

// Melakukan load relasi secara susulan
if ($needCategory) {
    $products->load('category');
}

Tips Laravel 13: Mencegah N+1 Problem Secara Otomatis

Agar kamu tidak pernah kecolongan melakukan Lazy Loading secara tidak sengaja saat proses development, tambahkan perintah berikut di app/Providers/AppServiceProvider.php:

PHP

namespace App\Providers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Mencegah Lazy Loading di lingkungan local/development
        Model::preventLazyLoading(! $this->app->isProduction());
    }
}

Dengan mengaktifkan fitur ini, Laravel 13 akan secara otomatis melemparkan exception/error jika ada kode kamu yang memicu N+1 Query Problem di lingkungan lokal, sehingga kamu bisa langsung memperbaikinya sebelum dirilis ke server production.

Kesimpulan

Memahami dan menerapkan Eager Loading di Laravel 13 adalah kemampuan wajib bagi setiap backend developer. Dengan menekan jumlah kueri ke database dari ratusan menjadi hanya beberapa kueri saja, kecepatan dan stabilitas aplikasi web milikmu akan meningkat secara signifikan.


Egi Samsul Mu'arif

Ditulis oleh

Egi Samsul Mu'arif

Web & Mobile Developer

Artikel Terkait

Lihat semua