When working with associations in Rails, both eager_load and includes help you avoid the N+1 query problem by preloading associated records. However, they behave slightly differently in how they execute SQL queries.
1. What is includes?
The Rails guides define includes as: With includes, Active Record ensures that all of the specified associations are loaded using the minimum possible number of queries.
This means that it preloads associated records to optimize queries, and dynamically decides between them to avoid the N+1 query problem, but it decides the SQL strategy dynamically based on usage.
Associated records are only loaded eagerly when accessed; if you do not access them, Rails will not load them eagerly.
Rails uses two strategies when associated records are accessed:
- It separates queries for the parents and associated records.
- It joins tables if conditions are applied to the associated records - similar to eager load
SQL query strategy:
Executes multiple queries (parent + associated records) by default, unless certain conditions require a LEFT OUTER JOIN.
The code above executes two queries, the parent and the associated record:
SELECT * FROM posts
SELECT * FROM comments WHERE post_id IN (…)
If conditions are applied, includes will generate a single query using LEFT OUTER JOIN, thereby reducing the number of queries to one.
Queries executed:
SELECT "posts".*
FROM "posts"
LEFT OUTER JOIN "comments"
ON "comments"."post_id" = "posts"."id"
WHERE "comments"."body" = 'example';
2. What is eager_load?
With eager_load, Active Record loads all specified associations using a LEF OUTER JOIN.
This forces Rails to load associated records using a single query and Always generates a LEFT OUTER JOIN between parent and associated records.
Query executed:
SELECT posts.*, comments.*
FROM posts
LEFT OUTER JOIN comments ON comments.post_id = posts.id
Key Differences
Includes:
- Separate queries by default or joins when necessary.
- It is efficient if associations aren’t accessed.
- It is efficient when you might not access associated records or need dynamic optimization.
Eager load:
- It always uses a LEFT OUTER JOIN.
- It loads everything upfront, even if unnecessary.
- Very efficient when you need all associations in one query.
How to Choose?
Use includes for most use cases, especially when you don’t always access associated records, and go for eager_load when you want everything in a single query or need to apply conditions on associated records.
That’s it! You now know when to use includes and eager_load to optimize your ActiveRecord queries effectively.
Top comments (0)