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