2

次のようなAPIからデータを取得しています:

[{"type": "a", "value": 1, "identifier": 1},
{"type": "b", "value": 9, "identifier": 1},
{...},{...},
{"type": "a", "value": 2, "identifier": n}]

識別子は 1 ~ 500 の任意の値にすることができ、すべてのレコードが同じ識別子を持つことは保証されません。識別子が存在する場合、それはすべて同じ型と特定の範囲の値を持ちます。レコードを更新するために最初に使用していたものは次のようになりました。

api_data.each do |x|
  temp = Object.find_or_create_by_type_and_identifier_and_id(x["type]", x["identifier"], user_id)
  temp.update_attributes(x)
end

これは信じられないほど遅く、このデータがロードされるたびに約 2200 のクエリが実行されます。1100 エントリに対して、データが存在するかどうかを確認するために 1 回、次に更新するために 1 回。現在使用されているテーブル スキームは次のようになります。

create table ( type, identifier, id, value)

これはobviously inefficient、私はどれだけ気づいていませんでした。新しいユーザー データを更新またはプルする必要があるときにアプリケーションがクロールしないように、クエリの数を減らすにはどうすればよいですか?

提案されている方法は、大量に挿入し、更新が必要なときに以前のエントリを削除することです。これにより、これが 2 に減少しますが、それが最善の方法であるかどうかはわかりません。

4

1 に答える 1

1

一括更新が必要な場合は、更新の性質によってはActiveRecord::Relation#update_allで済む場合があります。

activerecord-import gemは効率的な一括挿入を行います。更新メカニズムがあるかどうかはわかりませんが、すばやく挿入するには優れています (数千行の単一の SQL ステートメント)。約 2200 のレコード、いくつかの更新ロジック、欠落したレコードを挿入するための 1 つのステートメントに対する 1 つの高速クエリのみが必要です。

適度に極端ですが、おそらくはるかに高速な解決策は、DB 内のすべてのレコードをロードし、新しい状態を調整し、削除または変更するすべての行を削除し (高速一括操作)、activerecord- を使用して新しい/変更された行を一括挿入することです。輸入。これは、最大で 3 つのデータベース操作であり、〜 2200 レコードに対して非常に高速に実行されますが、変更のたびに実行したいほど高速ではありません。

最後に、SQL に頼ることができます。あなたの変更は、単純に実行できるほど基本的なものに見えますYourModel.connection.execute "UPDATE some_things SET foo = 'whatever'"。とはいえ、Railsy を使ってやりたいことを何でもできる方法があると思います。ActiveRecordのドキュメントを参照してください。、 などdelete_allの多くの一括操作があります。update_all

于 2013-03-19T20:16:43.717 に答える