使用方法update_all [英] update_all with a method
问题描述
让我们说我有一个模型:
Lets say I have a model:
class Result < ActiveRecord::Base
attr_accessible :x, :y, :sum
end
而不是这样做
Result.all.find_each do |s|
s.sum = compute_sum(s.x, s.y)
s.save
end
假定 compute_sum
是可用的方法,并且执行某些无法转换为SQL的计算。
assuming compute_sum
is a available method and does some computation that cannot be translated into SQL.
def compute_sum(x,y)
sum_table[x][y]
end
是否可以使用 update_all
,可能类似于:
Is there a way to use update_all
, probably something like:
Result.all.update_all(sum: compute_sum(:x, :y))
我要更新的记录超过80,000条。 find_each
中的每个记录都会创建自己的 BEGIN
和 COMMIT
查询,并且每个记录都会单独更新。
I have more than 80,000 records to update. Each record in find_each
creates its own BEGIN
and COMMIT
queries, and each record is updated individually.
或者还有其他更快的方法吗?
Or is there any other faster way to do this?
推荐答案
如果不能将compute_sum函数转换为sql,则无法一次对所有记录执行update_all。您将需要遍历各个实例。但是,如果列中有很多重复的值集,则可以加快速度,方法是每组输入仅进行一次计算,然后每次计算进行一次质量更新。例如
If the compute_sum function can't be translated into sql, then you cannot do update_all on all records at once. You will need to iterate over the individual instances. However, you could speed it up if there are a lot of repeated sets of values in the columns, by only doing the calculation once per set of inputs, and then doing one mass-update per calculation. eg
Result.all.group_by{|result| [result.x, result.y]}.each do |inputs, results|
sum = compute_sum(*inputs)
Result.update_all('sum = #{sum}', "id in (#{results.map(&:id).join(',')})")
end
您可以将result.x,result.y替换为
You can replace result.x, result.y with the actual inputs to the compute_sum function.
编辑-忘记在group_by块中的result.x,result.y周围放置方括号。
EDIT - forgot to put the square brackets around result.x, result.y in the group_by block.
这篇关于使用方法update_all的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!