has_many в Rails использует JOIN - PullRequest
1 голос
/ 28 ноября 2009

Мое понимание отношения has_many в Rails состоит в том, что он будет использовать JOIN для поиска связанных строк. Если бы я реализовывал это с нуля, я бы создал реляционную таблицу. Правильно ли я думаю, что будет медленнее использовать JOIN? В Django я считаю, что реляционные таблицы созданы, и я знаю, что могу использовать реляционную таблицу в Rails, если захочу Мне интересно, почему это поведение по умолчанию и имеет ли оно какое-либо значение.

Спасибо

Ответы [ 3 ]

2 голосов
/ 28 ноября 2009

Нет, по умолчанию отношение 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 голос
/ 28 ноября 2009

В ActiveRecord (который является ORM, используемым по умолчанию в Rails, но не единственным возможным), отношение has_many обычно включает две модели и, следовательно, две таблицы. Итак, эти модели:

class Order < ActiveRecord::Base
  has_many :order_items
end

class OrderItem < ActiveRecord::Base
  belongs_to :order
end

... будет ссылаться на таблицы orders и order_items, причем последняя имеет ссылку Foreign_key order_id на родительский порядок.

Order.find(some_id)

получит один заказ. order_items не будет затронут, если вы не ссылаетесь на него явно или не добавляете директивы в определение класса, чтобы требовать, чтобы ассоциация всегда находилась в навигации.

Я не уверен, почему вы так обеспокоены использованием соединений. При надлежащем индексировании практически любая современная СУБД будет очень эффективной: это то, для чего они предназначены.

1 голос
/ 28 ноября 2009

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

Если вам не нужно / не хотите присоединяться, тогда не будет никакого присоединения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...