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.
| Kondisi | Pilihan |
|---|---|
| Hanya mengambil satu model | Lazy Loading bisa cukup |
| Relationship belum tentu digunakan | Lazy Loading bisa dipertimbangkan |
| Relationship digunakan dalam loop | Eager Loading |
| Collection berisi banyak model | Eager Loading |
| API membutuhkan relationship | Eager Loading |
| Ingin menghindari N+1 Query | Eager Loading |
| Relationship baru diketahui setelah query | load() |
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.
