为了进行单个db查询,我急切地加载帖子及其翻译数据(使用rails 6和mobility(*),但它会生成两个sql查询:
# app/models/post.rb
class Post < ApplicationRecord
extend Mobility
translates :title, :description, backend: :table
end
# app/controllers/posts_controller.rb
class PostsController < ApplicationRecord
def index
@posts = Post.eager_load(:translations).limit(3)
end
end
<%# app/views/posts/index.html.erb %>
<% @posts.each do |post| %>
<h1><%= post.title %></h1>
<div><%= post.description %></div>
<% end %>
结果:
首先,选择所有post ID
然后使用中的where返回具有这些ID的帖子的所有属性
SELECT DISTINCT "posts"."id" FROM "posts"
LEFT OUTER JOIN "post_translations"
ON "post_translations"."post_id" = "posts"."id" LIMIT $1 [["LIMIT", 3]]
SELECT "posts"."id" AS t0_r0, "posts"."created_at" AS t0_r1, "posts"."updated_at" AS t0_r2, "post_translations"."id" AS t1_r0, "post_translations"."locale" AS t1_r1, "post_translations"."created_at" AS t1_r2, "post_translations"."updated_at" AS t1_r3, "post_translations"."title" AS t1_r4, "post_translations"."description" AS t1_r5, "post_translations"."post_id" AS t1_r6 FROM "posts"
LEFT OUTER JOIN "post_translations"
ON "post_translations"."post_id" = "posts"."id"
WHERE "posts"."id" IN ($1, $2, $3) [["id", "00060a7d-b846-5fc5-a372-1fc3462c695c"], ["id", "008db504-6fb4-5e90-bdca-4293ebe6d920"], ["id", "034944c1-4067-5ae5-89aa-4777ef14d66b"]]
如何避免内存中有ID的双sql语句?
(*)关于流动性的说明
mobility文档中有一些示例生成一条sql语句,但正如chris salzberg所指出的,在这个示例中根本没有使用它的查询api,因此不应该是罪魁祸首。为了试图证明这个问题可能与移动性无关,而是与活动记录本身有关,下面是一个从移动性中剥离出来的类似代码,它显示了相同的双重查询问题(注意:这只是为了演示,因为我确实希望继续使用移动性):
class Post < ApplicationRecord
has_many :translations, ->{ where(locale: I18n.locale) }
%i(title description).each do |attr|
define_method(attr) do
translations.first.send(attr)
end
end
class Translation < ApplicationRecord; end
end
<%# app/views/posts/index.html.erb %>
<% Post.eager_load(:translations).limit(3).each do |post| %>
<h1><%= post.title %></h1>
<div><%= post.description %></div>
<% end %>
1条答案
按热度按时间lo8azlld1#
如果您试图从集合中获取一些非常特定的属性,那么collectionproxy将为您提供单个查询。如果未提供任何属性(列),则在执行
OUTER JOIN
查询老实说,我还没有通读整个实现来确认它背后的原因。
但让我告诉你一件事。
在上面的例子中,您可以看到eager_load实现了您所期望的功能。类似的情况是,您没有提到所需的属性,我认为当它进行惰性计算时,它会选择一个
distinct
除了OUTER JOIN
查询希望这对你有所帮助。如果有任何意见,请发表,以便我可以澄清