Rails: Joins, Preload, Eager load and Includes

January 31, 2019 admin No Comments

Rails: Joins, Preload, Eager load and Includes

Rails: Joins, Preload, Eager load and Includes

Ruby on rails active record 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.

Conclusion

Most of the time we will be using joins and includes but it is good to have the knowledge of preload and eager_load so we can optimize the queries according to the situation.

Leave a Reply