gotchaphplaravelMajor
Eloquent N+1 Query Problem with Eager Loading
Viewed 0 times
n+1eager loadingwith()lazy loadingeloquent queriesquery optimizationorm performance
Problem
When iterating over a collection and accessing a relationship on each model, Laravel fires a separate SQL query per model. With 100 posts, accessing post->author produces 101 queries instead of 2.
Solution
Always eager load relationships you know you will access using with(). Use Post::with('author')->get() instead of Post::all(). For nested relations use dot notation: Post::with('author.profile')->get(). Enable query logging in development with DB::enableQueryLog() to catch violations early.
Why
Eloquent lazy-loads relationships on first access by default. Each access on an unloaded relation triggers a new SELECT. Eager loading uses a single WHERE id IN (...) query to fetch all related models at once.
Gotchas
- with() must be called before get(), not after
- load() can be called on an already-retrieved collection to lazy eager load: $posts->load('author')
- withCount() is available to count related records without loading them
- Nested eager loads like 'comments.likes' fetch all likes for all comments, which can itself become expensive
Code Snippets
Eager loading a relation
// Bad: N+1
$posts = Post::all();
foreach ($posts as $post) {
echo $post->author->name; // one query per post
}
// Good: eager load
$posts = Post::with('author')->get();
foreach ($posts as $post) {
echo $post->author->name; // no extra queries
}Revisions (0)
No revisions yet.