Hey guys, I have a simple question about eager loading that solves the n+1 problem.
If I used the with() method to eager load relationships that I'm not even looping through, meaning if I used
$users = User::with('posts')->all()
But didn't use
foreach ($users as $user)
{
$posts = $user->posts;
}
Would it have any effect on my application performance?
When you use the with method, it is going to do a database query to load all the information into memory.
Eg: Something like select * from posts where user_id in (1, 2, 3, 4, 5, ...)
Then it will need to construct the relationships on the model which will also take time and memory.
If you don't need the information, my advice would be don't load it.
But if you had 20 users you wanted to show the posts for, a single query to load those posts will be way more efficient than 20 separate queries to get the posts.
@aleahy
Thank you for your reply. I understand what you said, and my question was specifically to the line where you said, "If you don't need the information, my advice would be don't load it."
Why shouldn't I load it if I'm not using it?
Will it make the query that only fetches the users slower, as it will add 'posts' attribute to each user? Again, I'm fully aware of when to use with and how. I just don't know if it will have any side effects on my app if I add it when fetching the users and never use $user->posts.
@Moutee If you don't need the data, and you load it anyway, then you are slowing down some pages of your app for no reason. DB queries take time. Even if it's only one additional one. You may not notice it when the data is small, but when it is large, it starts becoming a serious problem and your response times will be slow.
I can understand that you just want to have it automatically eager loaded because it just saves you worrying about it. At some point in the future it will probably become a serious problem that will be a pain to fix because you will then have to work out how to only load the data you need in all the places you need it as you undo the auto-eager-loading.
@sm3rter Because the posts are used somewhere? Of course, there needs to be a loop somewhere because users are in a collection, but it's the same for any collection.
@sm3rter
Yes, there's no scenario for this on my mind as well. I'm just asking if it would have an effect on my application performance if I used it accidentally.
there's an easier way to do this, if by some chance there's some users that you wanted to load their posts
$users = User::all();
foreach ($users as $user) {
if ($someCondition) { // only load the posts of some users depending on what you what
$user->load('posts');
}
}
return $users;
something like this
$users = User::all();
foreach ($users as $user) {
if ($user->id === 1) { // only load the posts of user id 1
$user->load('posts');
}
}
return $users;
@skeith22
I understand your approach.
If I used the code in your example, I would have one query to fetch all users and one query to fetch the posts of the user with an id of 1, which is ideal. But if I have more than one user within the if condition, then I would run a query for each user to fetch their post(s), which is not actually good. So, we would use the with method here.
However, my question was if it would have an effect on my application if I used the method just in case.
@Moutee It will add another database query, and load all of the posts to memory. What that really means in terms of performance is for you to figure out, since we don't know your app.
But that's beside the point. You shouldn't do unnecessary things "just in case". If you don't use the posts, don't fetch them. If you need them later, then add the with() part. I'm struggling to understand why this is even a consideration.
@aleahy you're correct, but we don't know what his app really is. I'm just giving him options on what he wants to do with his app.
@mouteesabouni if your application is well optimized like only pulling a few data per page, then it's okay if you're not too concerned about performance. just be aware about it if you're pulling data in the hundreds or thousands, then you're better off with with. then again it depends on where you're gonna used that thing. Also, you can mark it as Best Answer for others if they ran into this as well.