Rails: Joins, Preload, Eager load and Includes
Rails: Joins, Preload, Eager load and Includes
In Rails, the most common methods used to fetch association data are joins, preload, eager_load, and Includes. We will discuss all of them in this blog.
1: Joins
It applies inner joins among the associations (without loading association data). It should match with at least one of the associated records, and because of it, duplicate records can be returned. It is used if we don’t want to access associations and only filter out records based on it as they are not loaded into memory and will result in N+1 queries if accessed. Example: Chapter.joins(:pages)SELECT “chapters”.* FROM “chapters” INNER JOIN “pages” ON “pages”.”chapter_id” = “chapters”.”id”
2: Preload
It results in a separate query to load association data (one query per association). It is used if we want to access the associations, as they will be loaded in memory, without applying any filters on them as to where clause is not supported on the associations and will result in an error. However, it can be used on the parent association itself. Example: Chapter.preload(:pages)SELECT “chapters”.* FROM “chapters” SELECT “pages”.* FROM “pages” WHERE “pages”.”chapter_id” IN (1)
3: Eager load
It results in a left outer join, so all the associations are loaded in a single query. It is used only if we want to access the associations, as they will be loaded in memory, and also want to filter out records on the basis of associations as where clause is supported or wants all the associations to be fetched in a single query. Example: Chapter.eager_load(:pages)SELECT “chapters”.”id” AS t0_r0, “pages”.”id” AS t1_r0 FROM “chapters” LEFT OUTER JOIN “pages” ON “pages”.”chapter_id” = “chapters”.”id” AND “chapters”.”id” IN (1)
4: Includes
Its default behaviour is of preload, but unlike Preload, we can apply where clause on associations which then changes its behaviour to eager_load or in case we want this as a default behaviour we can use references. Example: Chapter.includes(:pages)SELECT “chapters”.* FROM “chapters” SELECT “pages”.* FROM “pages” WHERE “pages”.”chapter_id” IN 1)In the above example, we can see there were two separate queries to fetch chapter and pages data. Chapter.includes(:pages).references(:pages)
SELECT “chapters”.”id” AS t0_r0, “pages”.”id” AS t1_r0 FROM “chapters” LEFT OUTER JOIN “pages” ON “pages”.”chapter_id” = “chapters”.”id” WHERE “chapters”.”id” IN (1)In the above example, we can see a single query fetches data for both chapters and pages.
Leave a Reply