我有一份背景作業,每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',那會更好。 –