【发布时间】:2017-10-29 00:28:38
【问题描述】:
我有一个后台作业,我每 10 分钟运行大约 5,000 个。每个作业都会向外部 API 发出请求,然后在我的数据库中添加新记录或更新现有记录。每个 API 请求返回大约 100 个项目,因此每 10 分钟我会进行 50,000 个 CREATE 或 UPDATE sql 查询。
我现在处理这个问题的方式是,返回的每个 API 项都有一个唯一的 ID。我在我的数据库中搜索具有此 ID 的帖子,如果存在,它会更新模型。如果它不存在,它会创建一个新的。
想象一下 api 响应是这样的:
[
{
external_id: '123',
text: 'blah blah',
count: 450
},
{
external_id: 'abc',
text: 'something else',
count: 393
}
]
设置为变量collection
然后我在我的父模型中运行这段代码:
class ParentModel < ApplicationRecord
def update
collection.each do |attrs|
child = ChildModel.find_or_initialize_by(external_id: attrs[:external_id], parent_model_id: self.id)
child.assign_attributes attrs
child.save if child.changed?
end
end
end
这些单独的调用中的每一个都非常快,但是当我在短时间内完成 50,000 次调用时,它确实会加起来并且会减慢速度。
我想知道是否有更有效的方法可以处理这个问题,我正在考虑做一些事情,比如:
class ParentModel < ApplicationRecord
def update
eager_loaded_children = ChildModel.where(parent_model_id: self.id).limit(100)
collection.each do |attrs|
cached_child = eager_loaded_children.select {|child| child.external_id == attrs[:external_id] }.first
if cached_child
cached_child.update_attributes attrs
else
ChildModel.create attrs
end
end
end
end
基本上我会保存查找,而不是预先进行更大的查询(这也很快),但会在内存中进行权衡。但这似乎不会花太多时间,也许会稍微加快查找部分的速度,但我仍然需要进行 100 次更新和创建。
是否有某种方法可以进行我没有想到的批量更新?还有什么明显的东西可以让这个过程更快,或者减少我正在做的查询吗?
【问题讨论】:
标签: ruby-on-rails performance postgresql optimization query-optimization