我有一份背景作业,每10分钟运行一次约5000个记录。每个作业都向外部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次更新并创建。
有没有某种方式我可以批量更新,我没有想到?还有什么其他明显的东西可以让它变得更快,或者减少我正在做的查询量?
啊,好吧,这是有道理的。我绝对喜欢一次完成所有创作的想法。我唯一可以预见的问题是'ChildModel.where(external_id:collection2.keys)','collection2.keys'可能长达100个密钥,对于这种情况来说,这不是一个非常有效的查询数组中的许多键? – goddamnyouryan
我不认为这应该是一个问题,我已经用'where'查询获取了1000列。但是,如果列没有被索引,那么这很重要。如果你索引'external_id',那会更好。 –