1

我在记录之间有以下关系: 在此处输入图像描述

给定一个项目记录,我需要一个与项目相关的所有资源相关的所有国家的列表。任何国家都不应出现超过一次。

为此忽略明显的性能问题,我可以向Resource添加一个方法:

  def countries
    resources.flat_map{|resource| resource.countries}.uniq
  end

我的问题有两个。

有没有办法以一种高性能的方式通过查询来实现这一点?如果没有,我应该如何处理这种情况?

[更新]

@MarekLipka 的建议是:

resources.includes(:countries).map(&:countries).flatten.uniq

然而,这会导致 60 次点击,对于 20 个项目,总共需要 0.4 秒:

资源负载 (1.2ms) SELECT "resources".* FROM "resources" WHERE "resources"."project_id" = 20 ORDER BY name

ResourceLocation Load (1.0ms) SELECT "resource_locations".* FROM "resource_locations" WHERE "resource_locations"."resource_id" IN (97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126)

Country Load (0.4ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" IN (19, 31, 64, 82, 197, 169, 1, 161, 167)

[更新]

joins我最近的尝试通过使用而不是上述解决方案的速度大约是上述解决方案的两倍,includes每个资源在大约 0.2 秒内命中 1 次:

Country.joins(resource_locations: {resource: :project}).where(resources: {project_id: self}).uniq
4

1 回答 1

1

这应该没问题:

resources.includes(:countries).map(&:countries).flatten.uniq

includes方法通过预加载适当的关联来解决 N+1 查询的问题。

于 2013-11-08T15:18:10.657 回答