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

前端 未结 6 1708
名媛妹妹
名媛妹妹 2020-12-15 18:37

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

相关标签:
6条回答
  • 2020-12-15 18:41

    :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.

    0 讨论(0)
  • 2020-12-15 18:42

    Joins will just join the tables and bringsselected 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

    You can find a detailed explanation with examples in this article of mine: Active Record Associations Tips & Tricks.

    0 讨论(0)
  • 2020-12-15 18:46

    :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.

    0 讨论(0)
  • 2020-12-15 18:51

    :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.

    0 讨论(0)
  • 2020-12-15 19:00
    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.

    0 讨论(0)
  • 2020-12-15 19:05

    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\""
    
    0 讨论(0)
提交回复
热议问题