Ruby on rails rake任务中的海量数据更新
我有一个名为Ruby on rails rake任务中的海量数据更新,ruby-on-rails,ruby,postgresql,rake-task,Ruby On Rails,Ruby,Postgresql,Rake Task,我有一个名为PageDensity的模型,它有大约500万行 当我创建项目PageDensity表时,在densitycoulmn中存储了精度为5位小数的浮点 现在要求改为四舍五入到小数点后两位 我只是写了一个任务来绕过所有的密度,但它使系统变得如此沉重,以致于出现问题。即使我不能使用查询,因为我的舍入是位更改,如0.57500将舍入为0.57,0.57600将舍入为0.58 到目前为止,我所尝试的只是: task round_densities: :environment do a
PageDensity
的模型,它有大约500万行
当我创建项目PageDensity
表时,在density
coulmn中存储了精度为5位小数的浮点
现在要求改为四舍五入到小数点后两位
我只是写了一个任务来绕过所有的密度
,但它使系统变得如此沉重,以致于出现问题。即使我不能使用查询
,因为我的舍入是位更改,如0.57500
将舍入为0.57
,0.57600
将舍入为0.58
到目前为止,我所尝试的只是:
task round_densities: :environment do
application_object = ApplicationController.new
time = Benchmark.realtime do
ActiveRecord::Base.transaction do
PageDensity.all.each {|p| p.update_attributes(density: application_object.round_number(p.density))}
end
end
puts '***************************************'
puts "Total Time Consumed #{time} seconds"
puts '***************************************'
end
我还尝试查询舍入,但失败:
select round(0.00500, 2)
#this returns 0.01 as this should return 0.00
我正在使用
postgres
进行psql查询
或使用rails
?您应该使用批处理,以便进行更改
PageDensity.all.each
与:
检查
但要做到这一点,您必须删除实际上毫无用处的事务
Sideremark,如果没有要触发的回调,请替换:
p.update_attributes(density: application_object.round_number(p.density))
与:
这将节省一些额外的时间。听起来您的舍入要求与正常舍入相比仅差0.001 在这种情况下,我认为您可以运行sql更新:
update page_densities set density = round(density - 0.001, 2)
这将是这样的:
0.011 => round(0.010, 2) => 0.01
0.015 => round(0.014, 2) => 0.01
0.016 => round(0.015, 2) => 0.02
0.02 => round(0.019, 2) => 0.02
我强烈建议您使用
.all.find\u each
更改.allbatches@apneadiving接得好,谢谢。这肯定会有所不同,但不是那样much@Matt我试过了,但没能提出这样的问题。因为这不同于我在问题中解释的普通取整查询。不过,我不太明白你的取整逻辑。您只需要截断最后3位吗?@Matt no.0.00100到0.00500
将向下舍入,即0.00
。而0.00600到0.00900
将被四舍五入,即0.01
。希望这是有道理的为什么你说交易是无用的?在我看来,失败不会带来诚信问题。所有元素都是独立的,这只是减少了内存使用。但不会改变所花费的时间。事实并非如此,因为一次加载内存中的所有内容会减慢所有操作的速度。毫无疑问,sql总是比orm操作好,我的答案只是优化了orm路径似乎是合法的。让我试一试628391张唱片仍然需要29分钟。有进一步改进的想法吗?恐怕没什么好主意。你必须以这样或那样的方式检查所有的记录。如果密度
不总是有一个值,那么您可以使用进行过滤,其中密度不为空
——但是考虑到您的列和表名,这种情况似乎不太可能发生。运气不好,字段中总是有一些值
update page_densities set density = round(density - 0.001, 2)
0.011 => round(0.010, 2) => 0.01
0.015 => round(0.014, 2) => 0.01
0.016 => round(0.015, 2) => 0.02
0.02 => round(0.019, 2) => 0.02