DEV3 Technologies home

DEV3 Developer Forum

How do I find and fix N+1 queries in Eloquent?

Laravel helpSolved0 views
dev3 ·

My posts index page is slow. The debug bar shows 101 queries for 100 posts, one extra query per post to load the author. How do I fix this and how do I stop it from happening again in Laravel 12?

#laravel#eloquent#performance

0

1 reply

dev3 · Accepted answer

That is the classic N+1 problem: one query loads the posts, then lazy loading $post->author runs one more query for each row.

Fix: eager load

$posts = Post::with(['author', 'tags'])->latest()->paginate(20);

This runs 3 queries (4 with the paginate() count query) no matter how many posts there are. Nested relations use dot notation: with('comments.user'). Select only the columns you need, but always include the foreign key:

Post::with('author:id,name')->get();

Aggregates without loading rows

Post::withCount('comments')->withSum('orderItems', 'qty')->get();

Load later when the collection already exists

$posts->load('author');           // always
$posts->loadMissing('author');    // only if not loaded

Make N+1 fail loudly in development

In AppServiceProvider::boot():

Model::preventLazyLoading(! app()->isProduction());

Any lazy load then throws a LazyLoadingViolationException, so you find the problem in development instead of production. Recent Laravel 12 releases (12.8 and later) also offer opt-in automatic eager loading: call Model::automaticallyEagerLoadRelationships() in boot() (it is off by default), or ->withRelationshipAutoloading() on a single query or collection. It is a handy safety net, but explicit with() is clearer and what most teams use.

Pitfalls

  • Calling $post->comments()->count() inside a loop is still one query per row. Use withCount.
  • Accessors that touch a relation cause hidden N+1. Eager load what the accessor needs.
  • whereHas filters but does not load. You still need with() if you display the relation.
  • Check the real count with Laravel Debugbar or Telescope, or DB::listen.
0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.