有超过40万,重新填充数据库需要5个小时

时间:2012-11-16 04:22:05

标签: sql ruby-on-rails scale

简单地运行

ElectricityProfile.find_each do |ep|
  if UserProfile.exists?(ep.owner_id) && ep.owner_type == 'UserProfile'
    ElectricityProfileSummary.create(ep)
  end
end

需要年龄(5小时)来填充表格。有没有更好的方法来填充数据库?

让我们说从数据库中获取所有数据并将其存储在数组,哈希等中,然后按下以创建数据库

ElectricityProfile.find_each do |ep|
  if UserProfile.exists?(ep.owner_id) && ep.owner_type == 'UserProfile'
    array_of_electricity_profiles.push(ep)
  end
end
ElectricityProfileSummary.mass_create(ep) # => or any other method :)

抱歉忘记提及我确实已经覆盖了方法create,它需要多个模型并创建ElectricityProfileSummary ......

create!(:owner_id => electricity_profile.owner_id,
        :owner_type => electricity_profile.owner_type,
        :property_type => electricity_profile.owner.user_property_type,
        :household_size => electricity_profile.owner.user_num_of_people,
        :has_swimming_pool => electricity_profile.has_swimming_pool,
        :bill => electricity_bill,
        :contract => electricity_profile.on_contract,
        :dirty => true,
        :provider => electricity_profile.supplier_id,
        :plan => electricity_profile.plan_id,
        :state => state,
        :postcode => postcode,
        :discount => discount,
        :has_air_conditioner => electricity_profile.has_air_conditioner,
        :has_electric_hot_water => electricity_profile.has_electric_hot_water,
        :has_electric_central_heating => electricity_profile.has_electric_central_heating,
        :has_electric_cooktup => electricity_profile.has_electric_cooktup
)

2 个答案:

答案 0 :(得分:1)

如果你可以将导入循环包装到一个事务块中,它应该极大地加速导入。请继续阅读关于ROR交易here

答案 1 :(得分:1)

在存储过程或原始SQL中执行此操作可能是最好的方法,因为ActiveRecord在处理那么多记录时可能非常昂贵。但是,您可以使用includesjoins加快速度。

看起来您只想创建ElectricityProfileSummary模型。我对你的人际关系看起来有点不确定,但假设你有以下几点:

class ElectricityProfile
  belongs_to :owner, polymorphic: true
end

class UserProfile
  has_many :electricity_profiles, as: owner
end

......你应该可以这样做:

ElectricityProfile.includes(:owner).each do |ep|
  ElectricityProfileSummary.create(ep)
end

现在,我假设您使用的是ElectricityProfile和UserProfile之间的多态关系。如果不是这样,请告诉我。 (我做了这个假设,因为你有owner_idowner_type,它们成对构成了多态关系所必需的两个字段。)

为什么使用包含更好?使用include会导致ActiveRecord急切加载两个模型之间的关系,因此您不会像现在这样进行n + 1个查询。实际上,因为你是根据ElectricityProfile记录的数量创建记录,你仍然在做n + 1,但你现在正在做的比n + 1贵,因为你正在为每一个ElectricityProfile查询UserProfile,然后你在创建ElectricityProfileSummary时再次查询UserProfile,因为你懒得加载EP和UP之间的关系。

当你做包含时,Rails将使用内连接在两个表之间进行查询。使用内部联接消除了确保UserProfile存在的必要性,因为内部联接仅返回关系两侧存在的记录。