4

私は、最近Ruby1.9.2とmysql2gemに更新された大規模なコードベースを持つ既存のRails2サイトで作業しています。この設定により、非ブロッキングデータベースクエリが可能になることに気づきました。client.query(sql, :async => true)実行して後で呼び出すことができますclient.async_result。これは、クエリが完了するまでブロックします。

ActiveRecordコレクションでメソッドが呼び出されるまで、コレクションを返すすべてのクエリのブロックを拒否することで、パフォーマンスを向上させることができるように思われます。例えば

@widgets = Widget.find(:all, :conditions=> conditions) #sends the query
do_some_stuff_that_doesn't_require_widgets
@widgets.each do #if the query hasn't completed yet, wait until it does, then populate @widgets with the result. Iterate through @widgets
...

これは、モンキーパッチBase::findとそれに関連するメソッドを使用して、新しいデータベースクライアントを作成し、クエリを非同期で送信し、すぐにDelegatorまたはその他のプロキシオブジェクトを返すことで実行できます。このオブジェクトは、メソッドが呼び出されると、呼び出しclient.async_resultて結果をインスタンス化します。を使用してActiveRecord、メソッドをそれに委任します。 ActiveRecordアソシエーションプロキシオブジェクトは、ORMを実装するためにすでに同様に機能します。

しかし、これを行った人は誰も見つかりません。また、どのバージョンのRailsでもオプションではないようです。私はそれを自分で実装しようとしましたが、コンソールで機能します(結果で呼び出されない; 1ように、すべてを呼び出す行に追加する限り)。to_sしかし、それは他のあらゆる種類の魔法と衝突し、さまざまな問題を引き起こしているようです。

それで、これは私が考えていなかった何らかの理由で悪い考えですか?そうでない場合、なぜそれはActiveRecordすでに機能していないのですか?それを実現するためのクリーンな方法はありますか?

4

1 に答える 1

1

その .async_result メソッドは、すべてのデータベース ドライバーで使用できるわけではないと思います。そうでない場合は、一般的な ActiveRecord 呼び出しにマージできるものではありません。

大規模なレコードセットをループするときにパフォーマンスを向上させる移植性の高い方法は、find_each または find_in_batches を使用することです。Rails 3.xだけでなくRails 2.3でも動作すると思います。http://guides.rubyonrails.org/active_record_querying.html#retrieving-multiple-objects-in-batches

于 2012-10-16T12:42:09.970 に答える