sort_by子查询耗时太长

时间:2015-02-12 21:00:58

标签: ruby-on-rails database postgresql optimization

我正在尝试优化从此RoR代码呈现的查询:

records.sort_by { |r| r.badge_instances.count }.reverse.each do |s|

这会产生N + 1个查询,因为对于每个record,需要有COUNT个查询。

为了澄清,badge_instancerecord的孩子。我可以使用哪些rails方法来呈现一个获取所有徽章实例计数的查询,并保留与每个record相关联的计数以进行排序?

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:3)

您可以在获取记录时执行一个查询,然后使用size而不是count来阻止N + 1个查询:

records = Record.include(:badge_instances).where(...)

records.sort_by { |r| r.badge_instances.size }.reverse.each do |s|
  ...
end

在与@MrYoshiji交谈时,如果这些表中的任何一个变得非常大,那么这可能会成为一个非常大的内存(因为这些对象的所有实例都将被加载到内存中。在这种情况下,替代方案可能是包括相关记录的计数作为查询中的属性:

records = Record.select("records.*, COUNT(badge_instances.id) as badge_instances_count").joins(:badge_instances).group("records.id")

然后,您可以访问名为records的每个badge_instances_count上的属性,您可以使用该属性按计数大小对记录进行排序。请注意,badge_instances_count将是一个字符串,因此需要将其转换为整数,以便按实际计数进行排序。