Rails中的has_many使用JOIN

时间:2009-11-28 17:46:10

标签: ruby-on-rails orm activerecord

我对Rails中has_many关系的理解是它将使用JOIN来查找相关的行。如果我从头开始实现这个,我会创建一个关系表。我是否认为使用JOIN会更慢?在Django中,我相信关系表是创建的,我知道如果我愿意,我可以在Rails中使用关系表。我想知道为什么这是默认行为,如果它有任何不同。

由于

3 个答案:

答案 0 :(得分:2)

不,默认情况下,has_many关系使用联接查找相关行。这是一个快速的命令行会话,显示了这一点(我的脚本/控制台启用了调试记录器)。

$ 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) 

但是,如果has_many关系定义了:through:include选项,则SQL将导致JOIN,但正确如此。

答案 1 :(得分:1)

如果您不告诉它,Rails将不会使用任何联接。

假设您拥有User模型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)) 

如果您不需要/想加入则不会加入。

答案 2 :(得分:1)

在ActiveRecord(默认情况下在Rails中使用的ORM但不是唯一可能的ORM)中,has_many关系通常涉及两个模型,因此涉及两个表。所以这些模型:

class Order < ActiveRecord::Base
  has_many :order_items
end

class OrderItem < ActiveRecord::Base
  belongs_to :order
end

...将引用ordersorder_items表,后者对其父订单有一个foreign_key order_id引用。

Order.find(some_id)

将检索单个订单。除非您明确引用它,否则不会触及order_items,或者将指令添加到类定义中以要求始终导航关联。

我不确定你为什么如此担心使用连接。通过适当的索引,几乎任何现代DBMS都将是高效的:它就是他们的目标。