2011-07-28 7 views
7

大規模なデータ移行(数100,000行)を実行すると、大きな時間と計算上の課題が発生しています。私はレールで多くのデータを扱うサービスを開発しています。私たちのモデルは絶えず変化しています。私たちのデザインについてはますます巧妙になっています。これにより、Postgres 9.0データベースであるデータベース上で多くの移行が行われます。しばしば、これらの移行にはデータ自体に何らかの移行が含まれています。昨日、モデルの「テキスト」属性を別のモデルに移動して、属性がモデルの単なる属性ではなく、1対多数の関係になるようにする必要があることがわかりました。レールで巨大なデータ移行を行う

私の移行は多少このように見えた:問題は、これはかなり遅い実行している、とさらに悪いことに、私はカウンタを設定した場合、および進捗状況を出力している、私はそれを見ることができるということであり、今

def self.up 
    create_table :car_descriptions do |t| 
    t.integer :car_id 
    t.text :description 

    t.timestamps 
    end 

    Car.find_each do |car| 
    if car.description.present? 
     car.descriptions.build :description => car.description 
    end 
    car.save 
    end 
    remove_column :cars, :description 
end 

マイグレーションは時間の経過と共に遅くなり、遅くなります。私の活動モニタでは、ルビープロセスがますます多くのメモリを占めていることがわかります。

私の質問ですが、このような大きなデータ移行を行うためのより良い方法はありますか?

答えて

12

CarモデルからCarDescriptionモデルへのデータの移行には、ActiveRecordを使用しないでください。代わりに、raw SQLの実行(移行から実行)までレトルトする必要があります。私の最後の仕事では、膨大なデータにこのような問題があり、raw sqlsを実行すると移行がずっと速くなりました。多くの苦い経験を​​経て、私たちが開発したもう1つのプラクティスは、私たちは常にプロダクションからステージングサーバーにデータベースをコピーし、ステージングで少なくとも2回マイグレーションを実行しました。私たちはいつも、このような習慣に従った大きな時間節約だったいくつかのプロセス(マイグレーションに特有)を考え出しました。場合によっては、手動でいくつかのインデックスを削除し、移行を実行し、それらのインデックスを再度手動で作成するプロセスも含まれていました。

現在のケースでは、SQLはこのような何か見ることができます:

INSERT INTO car_descriptions(car_id, description) SELECT id, description FROM cars 

をあなたはそれが役に立つ、私は答えに何かを追加することができますなら、私に知らせて見つけます。

+0

私にそれを打つ。これはあなたに1トンのメモリを節約するはずです。 – erik

+0

偉大な答え。私たちはそれもやってみましたが、もっと良いアプローチのように見えます。あなた自身の経験に関する少しのアドバイスをありがとう:-)私は[このリンク](http://railsapi.com/doc/rails-v3.0.8rc1/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html#M004596)をいくつか保持しています手作業のSQLステートメントを実行するときに、私たちのレールコードでちょっとしたものをきれいにするのに役立つメソッドに関する情報。 –

+0

@ニールズメソッドを使用することは、「マイグレーションから実行する」という意味でした。そこにリンクを追加する方が良いでしょう。 – rubish

関連する問題