Laravel Lazy Loading vs Eager Loading: Apa Bedanya dan Kapan Menggunakannya?

Laravel Lazy Loading vs Eager Loading

Ketika menggunakan Laravel Eloquent, kita sering bekerja dengan relationship seperti User memiliki banyak Post, Post memiliki Comment, atau Product memiliki Category.

Laravel menyediakan dua cara utama untuk mengambil data relationship:

  • Lazy Loading
  • Eager Loading

Perbedaan utama keduanya terletak pada kapan relationship diambil dari database.

Lazy Loading mengambil relationship ketika relationship tersebut benar-benar diakses.

Sedangkan Eager Loading mengambil relationship sejak awal menggunakan with().

Perbedaan ini terlihat sederhana, tetapi dapat memberikan dampak besar terhadap jumlah query database, terutama ketika data ditampilkan dalam jumlah banyak.

Apa Itu Lazy Loading di Laravel?

Lazy Loading adalah mekanisme ketika Laravel baru mengambil data relationship saat relationship tersebut diakses.

Misalnya model Post memiliki relationship author:

class Post extends Model
{
    public function author()
    {
        return $this->belongsTo(User::class, 'user_id');
    }
}

Kemudian kita mengambil sebuah post:

$post = Post::find(1);

Pada tahap ini Laravel mengambil data post terlebih dahulu.

Relationship author belum tentu di-query.

Ketika kode berikut dijalankan:

echo $post->author->name;

Laravel baru mengambil data author dari database.

Inilah yang disebut Lazy Loading.

Contoh Sederhana Lazy Loading

Misalnya terdapat tabel:

posts
- id
- user_id
- title

users
- id
- name

Kita mengambil post:

$post = Post::find(1);

Query utama:

SELECT * FROM posts WHERE id = 1 LIMIT 1;

Kemudian kita mengakses:

$post->author;

Laravel menjalankan query tambahan:

SELECT * FROM users WHERE id = 1 LIMIT 1;

Relationship baru diambil ketika diperlukan.

Kelebihan Lazy Loading

Lazy Loading memiliki beberapa keuntungan.

1. Sederhana

Kode yang digunakan sangat natural:

$post = Post::find(1);

echo $post->author->name;

Tidak perlu mendefinisikan relationship yang ingin diambil sejak query awal.

2. Data hanya diambil ketika dibutuhkan

Jika relationship tidak pernah digunakan, query untuk relationship tersebut tidak perlu dijalankan.

Contohnya:

$post = Post::find(1);

echo $post->title;

Jika author tidak pernah diakses, Laravel tidak perlu mengambil data author.

3. Cocok untuk Data Sederhana

Untuk mengambil satu model dan hanya sesekali mengakses relationship, Lazy Loading sering kali sudah cukup.

Apa Itu Eager Loading di Laravel?

Eager Loading adalah teknik untuk mengambil relationship sejak awal ketika query model dijalankan.

Laravel menyediakan method with() untuk melakukan Eager Loading.

Contohnya:

$posts = Post::with('author')->get();

Dengan kode tersebut, Laravel mengetahui bahwa relationship author akan dibutuhkan.

Secara umum Laravel akan menjalankan query seperti:

SELECT * FROM posts;

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

Setelah data diambil, kita dapat mengakses:

foreach ($posts as $post) {
    echo $post->author->name;
}

Tanpa harus membuat query author satu per satu untuk setiap post.

Lazy Loading vs Eager Loading

Perbedaan paling mudah dapat dilihat dari contoh berikut.

Lazy Loading

$posts = Post::all();

foreach ($posts as $post) {
    echo $post->author->name;
}

Relationship author diakses di dalam loop.

Jika terdapat banyak post, pola seperti ini dapat menyebabkan N+1 Query Problem.

Eager Loading

$posts = Post::with('author')->get();

foreach ($posts as $post) {
    echo $post->author->name;
}

Relationship author sudah dimuat ketika query awal dijalankan.

Ini biasanya lebih efisien untuk collection dengan jumlah data besar.

Mengapa Lazy Loading Bisa Menyebabkan N+1 Query?

Masalah N+1 biasanya muncul ketika Lazy Loading digunakan di dalam loop.

Misalnya:

$posts = Post::all();

foreach ($posts as $post) {
    echo $post->author->name;
}

Misalkan terdapat 100 post.

Laravel dapat menjalankan:

SELECT * FROM posts;

Kemudian relationship author dapat menyebabkan query tambahan:

SELECT * FROM users WHERE id = 1;
SELECT * FROM users WHERE id = 2;
SELECT * FROM users WHERE id = 3;

dan seterusnya.

Secara sederhana:

1 query  → mengambil posts
100 query → mengambil author

Total = 101 query

Inilah yang disebut N+1 Query.

Dengan Eager Loading:

$posts = Post::with('author')->get();

jumlah query dapat dikurangi secara signifikan.

Perbandingan Query Lazy Loading dan Eager Loading

Agar lebih mudah dipahami, kita bisa membandingkan keduanya.

Lazy Loading

$posts = Post::all();

foreach ($posts as $post) {
    echo $post->author->name;
}

Pola query:

Query 1: mengambil posts
Query 2: mengambil author
Query 3: mengambil author
Query 4: mengambil author
...

Jumlah query dapat bertambah mengikuti jumlah model yang mengakses relationship.

Eager Loading

$posts = Post::with('author')->get();

Pola query secara umum:

Query 1: mengambil posts
Query 2: mengambil users berdasarkan foreign key

Jadi relationship tidak perlu diambil satu per satu ketika loop berjalan.

Kapan Menggunakan Lazy Loading?

Lazy Loading bukan berarti buruk dan harus selalu dihindari.

Ada situasi ketika Lazy Loading justru lebih praktis.

1. Hanya Mengambil Satu Model

Misalnya:

$post = Post::findOrFail($id);

Kemudian kita membutuhkan author:

echo $post->author->name;

Untuk kasus sederhana seperti ini, Lazy Loading bisa saja cukup.

2. Relationship Tidak Selalu Dibutuhkan

Misalnya sebuah halaman terkadang hanya menampilkan informasi dasar post:

$post = Post::findOrFail($id);

echo $post->title;

Jika author tidak dibutuhkan, Lazy Loading tidak akan mengambil relationship tersebut.

Ini dapat menghindari query yang tidak diperlukan.

3. Logic Bersifat Conditional

Misalnya relationship hanya diperlukan dalam kondisi tertentu:

$post = Post::findOrFail($id);

if ($showAuthor) {
    echo $post->author->name;
}

Jika $showAuthor bernilai false, relationship tidak perlu diakses.

Kapan Menggunakan Eager Loading?

Eager Loading lebih cocok ketika kita sudah mengetahui bahwa relationship akan digunakan.

1. Relationship Digunakan dalam Loop

Ini adalah salah satu kondisi paling penting.

Hindari:

$posts = Post::all();

foreach ($posts as $post) {
    echo $post->author->name;
}

Gunakan:

$posts = Post::with('author')->get();

foreach ($posts as $post) {
    echo $post->author->name;
}

2. API Mengembalikan Relationship

Misalnya API mengembalikan daftar post beserta author:

$posts = Post::with('author')->get();

return response()->json($posts);

Eager Loading membantu memastikan relationship yang dibutuhkan sudah diambil sebelum data dikembalikan.

3. Halaman Membutuhkan Banyak Relationship

Misalnya halaman dashboard menampilkan:

  • User
  • Post
  • Comment
  • Category

Kita dapat menggunakan:

$posts = Post::with([
    'author',
    'category',
    'comments'
])->get();

Dengan begitu relationship yang dibutuhkan sudah ditentukan sejak awal.

Apakah Eager Loading Selalu Lebih Cepat?

Tidak selalu.

Ini adalah salah satu hal penting yang perlu dipahami.

Eager Loading dapat mengurangi jumlah query, tetapi bukan berarti semakin banyak relationship yang di-load maka performa semakin baik.

Contohnya:

$posts = Post::with([
    'author',
    'comments',
    'tags',
    'category',
    'likes',
    'attachments'
])->get();

Jika halaman hanya membutuhkan author, maka mengambil semua relationship tersebut justru dapat menyebabkan:

  • Data yang diambil lebih banyak
  • Memory yang digunakan lebih besar
  • Query tambahan yang sebenarnya tidak diperlukan
  • Response menjadi lebih berat

Jadi tujuan optimasi bukan sekadar mengurangi jumlah query, tetapi mengambil data yang memang dibutuhkan secara efisien.

Lazy Loading vs Eager Loading: Contoh Praktis

Misalnya kita memiliki halaman daftar produk.

Setiap produk memiliki category.

Pendekatan Lazy Loading

$products = Product::latest()->get();

Blade:

@foreach ($products as $product)
    <h2>{{ $product->name }}</h2>
    <p>{{ $product->category->name }}</p>
@endforeach

Jika terdapat banyak produk, akses $product->category dapat menghasilkan banyak query.

Pendekatan Eager Loading

$products = Product::with('category')
    ->latest()
    ->get();

Blade tetap sama:

@foreach ($products as $product)
    <h2>{{ $product->name }}</h2>
    <p>{{ $product->category->name }}</p>
@endforeach

Perbedaannya hanya pada query Eloquent, tetapi dampaknya dapat signifikan terhadap performa ketika jumlah data besar.

Bagaimana Mengetahui Apakah Terjadi N+1 Query?

Jangan hanya melihat kode PHP.

Perhatikan juga query yang benar-benar dijalankan.

Pada environment development, kita dapat menggunakan Laravel Debugbar atau tools profiling lainnya untuk melihat query database.

Laravel juga menyediakan DB::listen():

DB::listen(function ($query) {
    logger($query->sql, $query->bindings);
});

Dengan cara tersebut, kita dapat melihat query yang dieksekusi dan mencari pola query yang berulang.

Contohnya jika melihat:

SELECT * FROM users WHERE id = 1
SELECT * FROM users WHERE id = 2
SELECT * FROM users WHERE id = 3
SELECT * FROM users WHERE id = 4

dalam satu proses yang mengambil banyak post, hal tersebut patut diperiksa karena bisa menjadi indikasi N+1 Query.

Query profiling sebaiknya digunakan di environment development atau debugging terkontrol. Hindari logging query secara berlebihan di production.

Eager Loading dengan with()

Sintaks dasar Eager Loading adalah:

Post::with('author')->get();

Beberapa relationship sekaligus:

Post::with([
    'author',
    'category',
    'tags'
])->get();

Nested relationship:

Post::with('author.profile')->get();

Dengan kondisi:

Post::with([
    'comments' => function ($query) {
        $query->where('approved', true);
    }
])->get();

Pada Laravel modern, arrow function juga dapat digunakan:

Post::with([
    'comments' => fn ($query) => $query->where('approved', true)
])->get();

Lazy Eager Loading dengan load()

Selain with(), Laravel juga menyediakan load().

Perbedaannya adalah with() digunakan ketika membuat query awal, sedangkan load() digunakan setelah model sudah diperoleh.

Contohnya:

$post = Post::findOrFail($id);

$post->load('author');

Setelah itu kita dapat menggunakan:

echo $post->author->name;

Ini berguna ketika keputusan untuk mengambil relationship baru diketahui setelah model berhasil diambil.

with() vs load()

Secara sederhana:

Gunakan with() ketika relationship sudah diketahui sejak awal:

$posts = Post::with('author')->get();

Gunakan load() ketika model sudah diperoleh:

$post = Post::findOrFail($id);

$post->load('author');

Keduanya merupakan bagian dari strategi Eager Loading di Laravel.

Bagaimana Memilih Lazy Loading atau Eager Loading?

Gunakan aturan sederhana berikut.

KondisiPilihan
Hanya mengambil satu modelLazy Loading bisa cukup
Relationship belum tentu digunakanLazy Loading bisa dipertimbangkan
Relationship digunakan dalam loopEager Loading
Collection berisi banyak modelEager Loading
API membutuhkan relationshipEager Loading
Ingin menghindari N+1 QueryEager Loading
Relationship baru diketahui setelah queryload()

Namun, tabel tersebut bukan aturan mutlak.

Pemilihan yang tepat tetap bergantung pada jumlah data, query yang dijalankan, struktur relationship, dan kebutuhan aplikasi.

Best Practice Lazy Loading dan Eager Loading

Beberapa prinsip yang bisa digunakan dalam aplikasi Laravel:

1. Jangan Menggunakan Eager Loading Secara Berlebihan

Jangan memuat relationship yang tidak digunakan.

2. Waspadai Relationship di Dalam Loop

Kode seperti:

foreach ($posts as $post) {
    echo $post->author->name;
}

perlu diperiksa jika author belum di-load.

3. Gunakan with() Jika Relationship Sudah Diketahui

Post::with('author')->get();

4. Gunakan load() untuk Eager Loading Setelah Query

$post->load('author');

5. Periksa Query Aktual

Jangan hanya berasumsi kode sudah optimal. Gunakan query profiler atau logging pada development.

6. Jangan Mengejar Jumlah Query Semata

Query yang lebih sedikit belum tentu selalu berarti performa lebih baik.

Ukuran data, index database, memory, execution time, dan kebutuhan aplikasi juga harus dipertimbangkan.

Kesimpulan

Lazy Loading dan Eager Loading sama-sama merupakan fitur penting dalam Laravel Eloquent.

Perbedaannya terletak pada waktu relationship diambil:

  • Lazy Loading mengambil relationship ketika relationship diakses.
  • Eager Loading mengambil relationship sejak awal menggunakan with().
  • load() dapat digunakan untuk melakukan Eager Loading setelah model sudah diperoleh.

Lazy Loading praktis untuk kasus sederhana ketika relationship belum tentu diperlukan.

Sebaliknya, Eager Loading lebih cocok ketika relationship memang akan digunakan, terutama pada collection atau loop. Penggunaan with() juga dapat membantu menghindari N+1 Query Problem.

Contoh yang paling umum:

$posts = Post::with('author')->get();

Kemudian:

@foreach ($posts as $post)
    {{ $post->author->name }}
@endforeach

Kuncinya bukan memilih Lazy Loading selalu buruk atau Eager Loading selalu lebih baik.

Yang lebih penting adalah memahami kapan relationship dibutuhkan, berapa banyak data yang diproses, dan berapa banyak query yang benar-benar dijalankan.

Dengan memahami perbedaan Lazy Loading dan Eager Loading, kita dapat menulis aplikasi Laravel yang lebih efisien sekaligus menghindari masalah performa database yang sering muncul ketika aplikasi mulai memiliki banyak data.