我正在尝试提高代码性能的方法中使用这些模型和以下行。
class Location < ActiveRecord::Base
belongs_to :company
end
class Company < ActiveRecord::Base
has_many :locations
end
在方法中:
locations_company = []
###
found_locations = Location.within(distance, origin: from_result.split(',')).order("distance ASC")
### 0.002659s
###
found_locations.each do |location|
locations_company << location.company
end
### 45.972285s
###
companies = locations_company.uniq{|x| x.id}
### 0.033029s
代码具有此功能 - 首先,抓取指定半径内的所有位置。然后,从每个找到的行中取出公司并将其保存到准备好的阵列中。这是有问题的部分 - 每个循环需要45秒才能处理。
然后从这个新创建的数组中删除重复项。
我仍然想知道是否有更好的方法来解决这种情况,但我恐怕现在还没有看到它,所以我想问你们怎样才能加速.each
循环并将数据保存到数组中 - 在ruby中有更好的方法从对象中获取某些信息吗?
非常感谢您的时间,我整天沉浸在这个问题中,但仍然没有更有效的解决方案。
答案 0 :(得分:6)
最好的方法是不循环。您的最终目标似乎是找到指定区域内的所有公司。
found_locations = Location.within(distance, origin: from_result.split(',')).order("distance ASC")
companies = Company.where(id: found_locations.pluck(:company_id).uniq)
答案 1 :(得分:1)
我相信一直需要的东西不是each
,而是对数据库的查询。
第一行虽然构建查询但并没有真正运行它。
我相信如果您按如下方式编写代码:
locations_company = []
found_locations = Location.within(distance, origin: from_result.split(',')).order("distance ASC")
### this line will take most of the time
found_locations = found_locations.to_a
###
###
found_locations.each do |location|
locations_company << location.company_id
end
###
###
companies = locations_company.uniq{|x| x.id}
###
您会发现each
将花费更少的时间。您应该考虑优化查询。
正如@AlexPeachey在下面评论过的那样,location.company
也会涉及对列表中每个位置的查询,因为它是一种关系。您可能希望通过添加以下内容来急切地加载公司:
found_locations = Location.includes(:company).within(distance, origin: from_result.split(',')).order("distance ASC")
答案 2 :(得分:1)
问题不在于每个问题,而在于查询仅在您开始迭代时才开始执行。 found_locations
不是查询的结果,它是一个查询构建器,它将在需要时执行查询(例如,当您开始迭代结果时)。