我正在尝试优化从此RoR代码呈现的查询:
records.sort_by { |r| r.badge_instances.count }.reverse.each do |s|
这会产生N + 1个查询,因为对于每个record
,需要有COUNT
个查询。
为了澄清,badge_instance
是record
的孩子。我可以使用哪些rails方法来呈现一个获取所有徽章实例计数的查询,并保留与每个record
相关联的计数以进行排序?
非常感谢您的帮助!
答案 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
将是一个字符串,因此需要将其转换为整数,以便按实际计数进行排序。