Почему объединения в отношении, выполняющем несколько запросов в консоли - PullRequest
0 голосов
/ 07 апреля 2019

У меня 3 таблицы: biographies, affiliations, communities

Присоединение принадлежит биографиям и сообществам, то есть присоединение имеет biography_id и community_ids в качестве внешних ключей, все с отношениями has_one. Биография связана с сообществом через членство

в консоли рельсов, когда я выполняю:

b = Biography.joins(:affiliation => :community)

тогда это вывод sql:

 Biography Load (0.2ms)  SELECT  "biographies".* FROM "biographies" INNER JOIN "affiliations" ON "affiliations"."biography_id" = "biographies"."id" INNER JOIN "communities" ON "communities"."id" = "affiliations"."community_id" LIMIT ?  [["LIMIT", 11]]

Пока все хорошо, продолжая в том же сеансе консоли, затем я выполняю:

b.first.affiliation

Тогда вывод:

D, [2019-04-06T23:21:20.417201 #38967] DEBUG -- :   Biography Load (0.3ms)  SELECT  "biographies".* FROM "biographies" INNER JOIN "affiliations" ON "affiliations"."biography_id" = "biographies"."id" INNER JOIN "communities" ON "communities"."id" = "affiliations"."community_id" ORDER BY "biographies"."id" ASC LIMIT ?  [["LIMIT", 1]]

D, [2019-04-06T23:21:20.418180 #38967] DEBUG -- :   Affiliation Load (0.1ms)  SELECT  "affiliations".* FROM "affiliations" WHERE "affiliations"."biography_id" = ? LIMIT ?  [["biography_id", 1], ["LIMIT", 1]]

Во-первых: почему он выполняет еще одно соединение, не следовало ли использовать соединение из первого запроса activerecord?

секунда: почему есть другой журнал выбора? Разве он не должен использовать результат соединения вместо нового выбора?

Продолжая, когда я выполню:

b.first.affiliation.community

затем выводится еще один журнал выбора из сообществ.

На самом деле выполняется новый запрос или он просто получает результаты из памяти первого запроса? И как я могу сказать, реальная против памяти?

Спасибо.

Ответы [ 2 ]

1 голос
/ 07 апреля 2019

join в вашем первом запросе является внутренним соединением: он сообщает ActiveRecord загружать только биографии, для которых есть связи с сообществом.

Если вы хотите получить доступ к этим записям и избежать запроса N + 1, вы можете использовать дополнительный оператор includes или использовать eager_load.

Так что да: всякий раз, когда вы видите, как консоль выводит оператор SQL, это означает, что выполняется новый запрос.

0 голосов
/ 07 апреля 2019

b = Biography.joins(:affiliation => :community) означает получить все Biographies, которые имеют affiliation из community, что означает, что вы загружаете подмножество Biographies на основе условия inner join (родительская таблица должна иметь хотя бы одну ссылку в таблица ассоциаций).

Если вы хотите preload целых результатов, вы можете использовать:

b = Biography.preload(:affiliation => :community)

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