Created
March 8, 2020 02:06
-
-
Save luchiago/4acfa7a7241d24babd743b0a316662f4 to your computer and use it in GitHub Desktop.
Rails preload, eager_load and includes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example Models | |
class Tournament | |
attribute :name, :string | |
has_many :teams | |
end | |
class Teams | |
attribute :name, :string | |
attribute :position, :integer | |
attribute :points, :integer | |
belongs_to :tournament | |
end | |
# preload | |
=begin | |
Preload works generating two sql querys. | |
The first one is to load the model data, and the second one is to load the relationship and filter by the first model | |
If I want to use some filter, I should use the first model as filter, not the second one | |
=end | |
# Example of preload | |
Tournament.preload(:teams) | |
# SQL | |
SELECT "tournaments".* FROM "tournaments" # it will query everything (e.g. the name of tournament) of tournament | |
SELECT "teams".* FROM "teams" WHERE "teams"."tournament_id" IN (1) | |
# eager_load | |
=begin | |
eager_load uses a JOIN, specifically LEFT OUTER JOIN (or just LEFT JOIN), | |
which takes a join from the first table and the intersection with the second one | |
It forces one single query | |
=end | |
# Example of eager_load | |
Tournament.eager_load(:teams) | |
# SQL | |
SELECT "tournaments"."id" AS t0_r0, "tournaments"."name" AS t0_r1 \ | |
FROM "tournaments" LEFT OUTER JOIN "teams" ON "teams"."tournament_id" = "tournaments"."id" | |
# includes | |
=begin | |
Very like the above methods, uses a single query | |
And accept a filter from the second table, not from the first one | |
=end | |
# Example of includes | |
Tournament.includes(:teams).where('team.position = 1') | |
#SQL | |
SELECT "tournaments"."id" AS t0_r0, "tournaments"."name" AS t0_r1, "teams"."id" AS t1_r0, \ | |
"teams"."points" AS t1_r1, \ | |
"teams"."position" AS t1_r2, \ | |
"teams"."tournament_id" AS t1_r3 | |
FROM "tournaments" LEFT OUTER JOIN "teams" ON "teams"."tournament_id" = "tournaments"."id" | |
WHERE (team.position = 1) | |
# Differences and when I should use each one | |
=begin | |
They are very similar. The difference relies what kind of query I want to do and about the perfomance | |
each method will have for that query. preload will fires two querys, but eager_load and includes not. | |
And if you want to know if you should use eager_load instead of includes, use includes first and see | |
the generated sql (with to_a) and the performance, if is too slow, use eager_load which always use one single query | |
even haves a "where" | |
=end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment