开发者

What's the difference between "includes" and "joins" in ActiveRecord query?

What's the difference between "includes" and "joins" in ActiveRecord query? Can anyone explain to me with the following two associated models?

class Car < ActiveRecord::Base
  belongs_to :store
end

class Store < ActiveRecord::Base
  belongs_to :owner
 开发者_如何学编程 has_one :car
end


stores = Store.joins(:car)

This will return all stores for which there is a car. stores[0].car will result in another query.

stores = Store.includes(:car)

This will return all stores, car or no car. stores[0].car will not result in another query.

stores = Store.includes(:car).joins(:car)

This will return all stores with a car. stores[0].car will not result in another query. I wouldn't recommend this for has_many relationships, but it works great for has_one.


:joins joins tables together in sql, :includes eager loads associations to avoid the n+1 problem (where one query is executed to retrieve the record and then one per association which is loaded).

I suggest you read their sections in Rails Guides to get more info.


:joins returns read-only objects, :includes does not

:joins uses inner join, :includes uses outer join.

the main reason of :includes is eager loading, to avoid the N+1 problem of loading in attributes of each object using a separate query.


Joins will just join the tables and brings selected fields in return. if you call associations on joins query result, it will fire database queries again

Include will eager load the included associations and add them in memory. Include loads all the included tables attributes. If you call associations on include query result, it wont fire any queries


TL; DR

Joins:

a.joins(:b).to_sql
=> "SELECT \"a\".* FROM \"a\" INNER JOIN \"b\" ON \"b\".\"id\" = \"a\".\"b_id\""

Includes:

a.includes(:b).to_sql
=> "SELECT \"a\".* FROM \"a\"

Both:

a.includes(:b).joins(:b).to_sql
=> "SELECT \"a\".\"id\" AS t0_r0, \"a\".\"a_field_1\" AS t0_r1, \"a\".\"a_field_2\" AS t0_r2, \"a\".\"a_field_3\" AS t0_r3, \"b\".\"a_field_1\" AS t1_r1, \"b\".\"a_field_2\" AS t1_r2, \"b\".\"a_field_3\" AS t1_r3 FROM \"a\" INNER JOIN \"b\" ON \"b\".\"id\" = \"a\".\"plan_id\""


:joins is the ActiveRecord version of JOINS, the SQL request.

Store.joins(:car).to_sql
=> SELECT stores.* FROM stores INNER JOIN cars ON cars.store_id = categories.id

So behind the seen it is an implicit INNER JOIN. It will thus indeed return all stores that have a car (because of the inner_join, a left_outer_join would have had a different behaviour). See more here.

Whereas :includes is not a query command. It solves the n+1 query issue by eager_loading the Car model on the Store model. See more one eager_loading here.

stores = Store.includes(:car)

will thus return all stores, and allows to do stores.first.car without firing a new query.


Join: It uses lazy loading and it performs an inner join. joins to simply add two tables together

Includes: Includes uses eager loading and perform a left outer join and includes can also prevent the N+1 queries.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜