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.
精彩评论