2011-01-24 5 views
1

その「名前」の値にフィルタを適用することにより、テーブル全体を更新する必要があります。このコード:ルビーon RailsのActiveRecordの効率

entries = select('id, name').all 
entries.each do |entry| 
    puts entry.id 
    update(entry.id, { :name => sanitize(entry.name) }) 
end 

私はRuby on Railsをにかなり新しいですし、見つかったそれは興味深い、というのが私の選択クエリ単一の行選択に分割されています。

SELECT `entries`.* FROM `entries` WHERE (`entries`.`id` = 1) LIMIT 1 
SELECT `entries`.* FROM `entries` WHERE (`entries`.`id` = 2) LIMIT 1 
SELECT `entries`.* FROM `entries` WHERE (`entries`.`id` = 3) LIMIT 1 
... 

私は理解しているように、それはRailsのが提供する、最適化のようなものだ - 一度にそれが必要だだけの行(毎サイクル)ではなく、すべてのエントリを選択します。

しかし、この場合は本当に効率的ですか?つまり、データベーステーブルに1000のレコードがある場合、1つのクエリよりも1000のクエリを作成する方が良いでしょうか?そうでない場合、どのようにRailsにクエリごとに複数の行を選択させることができますか?

もう1つの質問は、このクエリによってすべての行が更新されるわけではありません。提供された値がすでに存在する場合(つまり、entry.name == sanitize(entry.name)の場合)、Railsは更新クエリを無視しますか?

答えて

1
Entry.find_each do |entry| 
    #... 
end 

これは、すべてのエントリ(クエリごとに100個)を取り出し、各エントリを公開します。

属性が変更されない場合、RailsはUPDATEクエリを実行しません。

2

ActiveRecordは抽象レイヤーですが、特定の操作(特に大きなデータセットを含む操作)を行う場合、抽象レイヤーの下で何が起こっているのかを知ることは有益です。

これは、ほとんどすべての抽象化に当てはまります。 (漏れやすい抽象化のジョエル・スポルスキの古典的な記事を参照してください。http://www.joelonsoftware.com/articles/LeakyAbstractions.html

をここでのポイントにケースに対処するために、Railsはupdate_all方法

を提供します
関連する問題