【问题标题】:Rails eager loading doesn't work(still n+1)Rails 急切加载不起作用(仍然 n+1)
【发布时间】:2017-08-03 13:49:54
【问题描述】:

我已经包含了 client_person 和 case_histories 但是在查询 case_histories 时它仍然会生成 n+1 查询。 我已经尝试了很长时间,但似乎没有任何效果。

@client_records = @records.includes({person: [:client_person, :case_histories]})

个人模型: belongs_to :client_person, class_name: 'Client::Person' has_many :case_histories, through: :region_profiles, class_name: 'Admin::PeopleCaseHistory'

生成 n+1 的查询:

@client_records.each do |record|
  record.person.case_histories.select{ |hist| hist.case_type == 2}.first
end

具体来说,在正确加载列表中所有客户端的case_histories后(由includes子句产生),它仍然会一一查询每个客户端的case_histories。

由 include 生成的第一个查询:

Admin::PeopleCaseHistory Load (46.9ms)  SELECT "case_histories".* FROM "case_histories" WHERE "case_histories"."region_profile_id" IN (411, 16804, 572, 19506, 16539, 692, 4828)

随后的 N+1 个查询:

Admin::PeopleCaseHistory Load (29.5ms)  SELECT "case_histories".* FROM "case_histories" INNER JOIN "region_profiles" ON "case_histories"."region_profile_id" = "region_profiles"."id" WHERE "region_profiles"."person_id" = $1  [["person_id", 9867]]

Admin::PeopleCaseHistory Load (34.3ms)  SELECT "case_histories".* FROM "case_histories" INNER JOIN "region_profiles" ON "case_histories"."region_profile_id" = "region_profiles"."id" WHERE "region_profiles"."person_id" = $1  [["person_id", 430]]

请指教! 谢谢

【问题讨论】:

  • 尝试用references替换includes
  • 这不起作用
  • 您看到重复的 N+1 查询是什么?
  • @Smudge 我在帖子中添加了 N+1 查询
  • 更新了我的答案,但可能仍需要更多信息

标签: ruby-on-rails ruby activerecord eager-loading


【解决方案1】:

您的case_histories 表中似乎同时存在people_region_profile_idregion_profile_id。其中一个在急切加载期间被使用,但另一个没有。

列出整个模型/关系图会对您有所帮助,因为我无法构建到底发生了什么。在我看来,您的图表看起来像这样:

class Person < ActiveRecord::Base
  belongs_to :client_person
  has_many :region_profiles
  has_many :case_histories, through: :region_profiles
end

class RegionProfile < ActiveRecord::Base
  belongs_to :person
  has_many :case_histories
end

class CaseHistory < ActiveRecord::Base
  belongs_to :region_profile
end

但如果 case_histories 有两个不同的外键,我显然会遗漏一些东西。

【讨论】:

  • 抱歉,我在帖子中打错了字。我的代码确实是 record.person.case_histories.select { |hist| hist.case_type == 2 }.first 但是这会生成 n+1
  • 啊,在这种情况下,我会仔细检查你的遍历——确保你没有无意中通过region_profiles。如果这不起作用,我会加载 rails c 并手动尝试该代码 - 在运行 client_records.first.person.case_histories.to_a 等时注意查询。
猜你喜欢
  • 2017-09-14
  • 1970-01-01
  • 2010-10-25
  • 2011-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多