我的Rails应用程序具有以下条件:
每个Style
都有许多Bookings
每个Booking
都有一个warehouse
值和一个netbooked
值
我需要更新每个warehouse_netbooked
的{{1}}列,其中包含所有样式预订中每个Style
的总netbooked
总和的哈希值
我当前的代码有效,但速度太慢(每次迭代需要0.5秒,并且有数千种样式):
warehouse
答案 0 :(得分:0)
这里对您的代码进行了一些小改动,以避免在@ eric-duminil建议之后进行多次查询
CATiledLayer
我希望它可以帮到你。
答案 1 :(得分:0)
在您的情况下,您有一种风格,您正在预订3种类型的仓库,为每种类型的仓库查找上网本的总和。这是非常低效的。
一个好的规则是,首先从数据库中获取所需的数据,并在获取数据后使用ruby来处理数据。获取所需数据非常重要。因此,在您的情况下,您可以获取样式和所有相关的预订。然后,您可以遍历预订集合并准备style_warehouse_bookings
哈希。
find_each
代替each
includes
或preload
预加载数据。这是一个简单的例子,它肯定会提高性能,
warehouses = ["WH1","WH2","WH3"]
# preload bookings with style, `preload` used explicitely instead of `includes` to prevent cross join queries.
styles = Style.joins(:bookings).where('bookings.warehouse' => warehouses).preload(:bookings)
# find_each fetches data in batches of 1000 records
styles.find_each do |s|
style_warehouse_bookings = Hash.new
warehouses.each do |wh|
# select and sum methods of ruby are used instead of where and sum of active-record
total_netbooked = s.bookings.select{ |booking| booking.warehouse = wh }.sum(&:netbooked)
style_warehouse_bookings[wh] = total_netbooked
end
s.update(warehouse_netbooked: "#{style_warehouse_bookings}")
end
在eager loading associations documentation深入了解preload
,includes
和joins
。除此之外,我写了一篇关于何时使用preload
,includes
和joins
here的文章可以提供帮助。
答案 2 :(得分:0)
我认为您想要批量更新。如果我是正确的,请检查以下内容 链路
Is there anything like batch update in Rails?
此外,您可以引入事务以避免过多的提交 例如
def assign_warehouse_bookings
Style.transaction do
<your remaining code goes here>
end
end