19

I have a Rails 3 app running an older version of Spree (an open source shopping cart). I am in the process of updating it to the latest version. This requires me to run numerous migrations on the database to be compatible with the latest version. However the apps current database is roughly around 300mb and to run the migrations on my local machine (mac os x 10.7, 4gb ram, 2.4GHz Core 2 Duo) takes over three days to complete.

I was able to decrease this time to only 16 hours using an Amazon EC2 instance (High-I/O On-Demand Instances, Quadruple Extra Large). But 16 hours is still too long as I will have to take down the site to perform this update.

Does anyone have any other suggestions to lower this time? Or any tips to increase the performance of the migrations?

FYI: using Ruby 1.9.2, and Ubuntu on the Amazon instance.

4

5 に答える 5

3
  • 事前にインデックスを削除し、後で再度追加することをお勧めします。

  • また、既に述べたように、.where(...).each を .find_each に置き換え、おそらくトランザクションを追加すると役立つ場合があります。

  • .save! を置き換えます。.save(:validate => false) を使用すると、移行中にユーザーからランダムな入力が得られないため、既知の適切な更新を行う必要があり、検証は実行時間の多くを占めます。または、 .update_attribute を使用すると、1 つのフィールドのみを更新する検証もスキップされます。

  • 可能であれば、ループ内で使用する AR オブジェクトの数を減らします。それらをインスタンス化し、後でガベージ コレクションを行うと、CPU 時間がかかり、より多くのメモリが使用されます。

于 2012-08-02T13:45:21.587 に答える
0

この答えは、特定の技術的解決策というよりもアプローチに関するものです。主な基準が最小のダウンタイム(そしてもちろんデータの整合性)である場合、これに対する最善の戦略はレールを使用しないことです!

代わりに、すべての面倒な作業を前もって行い、重要な「リアルタイム」データ移行(ここでは非レールの意味で「移行」を使用しています)をスイッチオーバー中のステップとして残すことができます。

これで、dbスキーマと本番データを含む現在のアプリができました。また、(おそらく)新しいdbスキーマを使用してアップグレードされたスプリージェムに基づいたアプリの開発バージョンがありますが、データはありません。あなたがしなければならないのは、2つの間でデータを変換する方法を理解することです。これは、さまざまな方法で実行できます。たとえば、必要に応じて純粋なSQLと一時テーブルを使用したり、SQLとrubyを使用して挿入ステートメントを生成したりします。これらの手順を分割して、かなり「静的」なデータ(参照テーブル、製品など)を事前にデータベースにロードし、より頻繁に変更されるデータ(ユーザー、セッション、注文など)をデータベースにロードできるようにすることができます。移行ステップ中に実行されます。

このexport-transform-importプロシージャをスクリプト化して、繰り返し可能にし、完了後にテスト/チェックを行ってデータの整合性を確認できるようにする必要があります。スイッチオーバー中に新しい本番データベースへのアクセスを調整できる場合は、それに対してスクリプトを簡単に実行できるはずです。リリースプロセス(webistranoなど)に制限されている場合は、Railsの移行に参加する必要があるかもしれませんが、executeを使用して生のSQLを実行できます。

于 2012-07-29T05:49:49.393 に答える
0

たぶん、あなたはすでにこれを検討しています:

  1. すべてがディスク上にあること (WAL や fsync がないなど) を気にしないように db に伝えてください。これで、非常に大きな違いを生むメモリ内 db ができました。(データベースをオフラインにしたので、停電などの万一の場合にバックアップから復元できます)。完了したら、fsync/WAL をオンにします。

  2. データベースをオフラインにする前に、いくつかの移行を実行できる可能性があります。もちろんステージング環境でこれをテストします。その大規模なユーザーの移行は、ライブで実行できる可能性が非常に高いです。少し変更する必要があるかもしれません。

私はあなたの正確な状況に精通していませんが、これで十分でない限り、できることは他にもあると確信しています.

于 2012-07-26T23:58:30.890 に答える
0

この宝石を見てください。 https://github.com/zdennis/activerecord-import/

data = []
data << Order.new(:order_info => 'test order')
Order.import data
于 2012-08-05T22:02:37.833 に答える
0

残念ながら、格下げされたソリューションが唯一のソリューションです。レールで本当に遅いのはアクティブレコードモデルです。は、このようなタスクには適していません。

迅速な移行が必要な場合は、SQL で行う必要があります。

別のアプローチがあります。ただし、ほとんどの移行は常に書き直す必要があります...

于 2012-08-23T12:17:53.220 に答える