对这个有点头疼,我目前的代码看起来像这样:
tmarray = TM.select(:id).where('product_name ILIKE ? AND valid_from = ? AND promotional_text ILIKE ?', "#{eventname}%", "#{row.date.strftime('%Y-%m-%d')}", "#{row.eventvenuename}")
if tmarray
tmarray.each do |tm|
tm.update(event_id: row.id)
end
end
目前这需要3个小时才能在30,000行上运行。
什么是更快速的方式来做到这一点?
我一直在寻找ActiveRecord导入,但不是100%确定如何让它适用于更新?
谢谢
编辑
下面是完整的代码:
task populate: :environment do
begin
Event.all.each do |row|
eventname = row.eventname
if eventname.include? "UnderGround Presents "
eventname = eventname.gsub('UnderGround Presents ', '')
end
if eventname.include? "&"
eventname = eventname.gsub('&', 'and')
end
tm_array = TM.where('product_name ILIKE ? AND valid_from = ? AND promotional_text ILIKE ?', "#{eventname}%", "#{row.date.strftime('%Y-%m-%d')}", "#{row.eventvenuename}")
tm_array.find_each do |tm|
tm.update(event_id: row.id)
end
end
rescue Faraday::TimeoutError
puts "Connection failed"
next
end
end
您可以使用find_each
(https://apidock.com/rails/ActiveRecord/Batches/find_each)减少Rails在内存中一次加载的记录数量。
在你的情况下,它将是:
tm_array = TM.where('product_name ILIKE ? AND valid_from = ? AND promotional_text ILIKE ?', "#{eventname}%", "#{row.date.strftime('%Y-%m-%d')}", "#{row.eventvenuename}")
tm_array.find_each do |tm|
tm.update(event_id: row.id)
end
更新问题后编辑:您的整个任务可能变为:
task populate: :environment do
begin
Event.find_each do |event| # << this changed from .all.each to .find_each
eventname = event.eventname.gsub('UnderGround Presents ', '')
eventname = eventname.gsub('&', 'and')
tms = TM.where('product_name ILIKE ? AND valid_from = ? AND promotional_text ILIKE ?', "#{eventname}%", "#{event.date.strftime('%Y-%m-%d')}", "#{event.eventvenuename}")
# Option 1
tms.find_each do |tm|
tm.update(event_id: event.id)
end
# Option 2 (if you do not need to run validations/callbacks on the TM records)
tms.update_all(event_id: event.id)
end
rescue Faraday::TimeoutError
puts 'Connection failed'
next
end
end
建议的改进:
tms.update_all(event_id: event.id)
(再次,这将不会运行回调/验证,所以确保在你的情况下不需要它)(它也不会更新updated_at
列,但你可以简单地做tms.update_all(event_id: event.id, updated_at: DateTime.now)
)valid_from
列成为数据库中的date
类型,并直接使用event.date
而不将其转换为特定的格式化字符串product_name
,valid_from
和promotional_text
上创建索引(请参阅pg_trm
extension并在索引列上启用ILIKE
)promotional_text ILIKE ?
替换promotional_text = ?
,因为不需要ILIKE(你搜索完全相同的名字)。