开发者

has_many in Rails uses a JOIN

开发者 https://www.devze.com 2022-12-12 22:56 出处:网络
My understanding of the has_many relationship in Rails is that it will use a JOIN to find related rows. If I were implementing this from scratch I would have created a relation开发者_高级运维al table.

My understanding of the has_many relationship in Rails is that it will use a JOIN to find related rows. If I were implementing this from scratch I would have created a relation开发者_高级运维al table. Am I correct in thinking it will be slower to use a JOIN? In Django, I believe the relational tables are created, and I know that I can use a relational table in Rails if I want to. I am wondering why this is the default behavior and if it makes any difference at all.

Thanks


No, by default, a has_many relationship does not use a join to find related rows. Here's a quick command line sessions that show this (I have a debug logger turned on for my script/console).

$ rails has_many_test

$ cd has_many_test

$ ruby script/generate model account

$ ruby script/generate model user account_id:integer

$ rake db:migrate

$ ruby script/console
Loading development environment (Rails 2.3.4)
>> Account.has_many :users
>> a = Account.create
  Account Create (0.4ms)   INSERT INTO "accounts" ("created_at", "updated_at") VALUES('2009-11-28 18:06:50', '2009-11-28 18:06:50')
>> a.users
  User Load (0.3ms)   SELECT * FROM "users" WHERE ("users".account_id = 1) 

However, if the has_many relationship defines :through or :include options, the SQL will result in a JOIN, but correctly so.


In ActiveRecord (which is the ORM used by default within Rails but not the only one possible) a has_many relationship will typically involve two models and hence two tables. So these models:

class Order < ActiveRecord::Base
  has_many :order_items
end

class OrderItem < ActiveRecord::Base
  belongs_to :order
end

...will reference orders and order_items tables, the latter having a foreign_key order_id reference to its parent order.

Order.find(some_id)

will retrieve a single order. order_items won't be touched unless you reference it explicitly, or add directives into your class definition to require the the association always be navigated.

I'm not sure why you're so concerned about using joins though. With appropriate indexing almost any modern DBMS will be highly efficient: it's what they're designed to do.


Rails won't use any joins if you won't tell it to do so.

Let's say you have a User model with has_many :posts:

User.all
# SELECT * FROM `users`

User.all :joins => :posts
# SELECT `users`.* FROM `users` INNER JOIN `posts` ON posts.user_id = users.id

User.all :include => :posts
# SELECT * FROM `users`
# SELECT `posts`.* FROM `posts` WHERE (`posts`.user_id IN (1,2)) 

If you don't need/want to join then there will be no join.

0

精彩评论

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