2011-08-12 19 views
1

rails/ruby​​(レール3とruby 1.9.2を使用)に新しく、いくつかの不必要なクエリを実行しようとしています。Rails/Active Record。save!効率的な質問

私は各やる実行しているとき:

apples.to_a.each do |apple| 
    new_apple = apple.clone 
    new_apple.save! 
end 

と私は、SQLログをチェックし、私は1つのINSERTステートメントに続く3つのSELECT文を参照してください。 select文はまったく必要ないようです。たとえば、次のようなものです。

SELECT Fruit。* from Fruits where Fruit.ID = 5 LIMIT 1;
Select Color。* from Colors where Color.ID = 6 LIMIT 1;
SELECT TreeType。* from TreeTypes where TreeType.ID = 7 LIMIT 1;
リンゴ(Fruit_id、color_id、treetype_id)に挿入する値(6,7,8)戻り値 "id";

私は70kのインサートを走らせているのに、インサートごとに3つの選択がかなりの時間を費やすことに賭けています。

だから私は、次のことを思ったんだけど:

  • はActiveRecordの/のRails .SAVEのこの典型的です!以前の開発者がカスタムコードを追加しましたか?
  • これらの3つの選択ステートメントは、それぞれの項目に対して実行されると、余分な時間がかかりますか?
  • レール/アクティブレコードに組み込まれていると、より効率的に実行できるようにするには簡単にバイパスされますか?

答えて

3

あなたは、発生するようなことのために保存するには、このような何かあなたの関連を検証しなければなりません:関係は、レコードがロードされなければならないことを検証するために

class Apple < ActiveRecord::Base 
    validates :fruit, 
    :presence => true 
end 

を、これはする必要がありますレコードごとに個別に検証が行われます。それはあなたが危険な生活のように感じる場合は、検証せずに保存することができsave!

の標準的な動作です:

apples.to_a.each do |apple| 
    new_apple = apple.clone 
    new_apple.save(:validate => false) 
end 

より良いアプローチは、あなたのRDBMSがサポートしていれば大量の挿入を行うことによって、SQLでレコードを直接操作することです。たとえば、MySQLは1つのINSERT呼び出しで何千もの行を挿入させます。通常は、Apple.connectionアクセスレイヤーを使用して、任意のSQLコールを任意のSQL呼び出しで行うことができます。execute

0

私は、before_save EDIT:または果物の色と種類を見て、残りの属性と一緒に果物を保存している場合は、これらの検索は必要です。

通常、私はアクティブレコードにするとは思いません不要なルックアップ - それは常に効率的であることを意味するわけではありません...

+0

公正であるために、ActiveRecordは時にはあなたが何をするように言っているのか分からない。 – tadman