18

update_all300,000 レコードの列をすべてさまざまな値で更新したい場合、どのように使用できますか?

私がやりたいことは次のようなものです:

Model.update_all(:column => [2,33,94,32]).where(:id => [22974,22975,22976,22977]) 

しかし、残念ながらこれは機能せず、300,000 エントリの場合はさらに悪化します。

4

4 に答える 4

5

あなたの質問に対する簡単な答えは、できません。

update_all のポイントは、すべてのレコードの列に同じ値を割り当てることです (条件が指定されている場合は一致します)。便利な理由は、単一の SQL ステートメントでそれを行うためです。

正しさについてのシメの答えに同意します。ただし、 n SQL 呼び出しが生成されます。ですから、あなたの問題には、あなたが私たちに伝えていない何かがあるかもしれません。おそらく、その値で更新する必要があるオブジェクトに対して update_all を呼び出して、可能な値ごとに反復することができます。次に、適切なハッシュを作成するか、さらに良いことに、条件がモデル自体の何かに基づいている場合は、その条件を update_all に渡すことができます。

于 2012-01-07T17:19:00.123 に答える
4

これが私の2020年の答えです:

  1. 最も支持された答えは間違っています。著者自身が述べているように、n行ごとに 1 つずつ、SQL クエリをトリガーします。

  2. 2番目に支持された回答は、gem「activerecord-import」を提案しています。これが進むべき道です。ただし、これは ActiveRecord モデルをインスタンス化することによって行われます。また、このような gem のビジネスを行っている場合は、おそらく極端なパフォーマンスを求めているでしょう (いずれにせよ、これは私たちの場合でした)。

これが私たちがしたことです。まず、 hash の配列を作成します。各ハッシュにidは、更新するレコードの とその他のフィールドが含まれています。

例えば:

records = [{ id: 1, name: 'Bob' }, { id: 2, name: 'Wilson' },...]

次に、次のように gem を呼び出します。

YourModelName.import(records, on_duplicate_key_update: [:name, :other_columns_whose_keys_are_present_in_the_hash], validate: false, timestamps: false)

説明:

  • on_duplicate_key_updateつまり、データベースが主キーで競合を検出した場合 (既存のレコードの更新について話しているため、すべての行で競合が発生します)、失敗せず、代わりにその配列で渡す列を更新します。

  • そうしないとvalidate false(デフォルトは true)、行ごとに新しいモデル インスタンスをインスタンス化しようとし、検証のために失敗する可能性があります (ハッシュには部分的な情報しか含まれていないため)。

  • timestamp falseもオプションですが、そこにあることを知っておくとよいでしょう。

于 2020-09-18T21:36:10.837 に答える