0

特に関係をモデル化する方法として、Redisを使用してActiveRecordモデルを補完するというアイデアを読んだり遊んだりしています。このようなスクリーンキャストもいくつか見ました:http ://www.youtube.com/watch?v = dH6VYRMRQFw

一度に1つのオブジェクトをフェッチする場合は良い考えのように思えますが、オブジェクトのリストとそれらの各関連付けを表示する必要がある場合(たとえば、ビューまたはAPIの場合のJSON応答)。

純粋にActiveRecordを使用する場合は、includes読み込みを熱心に使用してN個以上のクエリを実行しないようにすることができますが、Redisに純粋に依存して関係をモデル化する場合、その方法を考えることはできません。

たとえば、次のものがあるとします(非常に役立つredis_on_railsプロジェクトから取得)。

class Conference < ActiveRecord::Base

  def attendees
    # Attendee.find(rdb[:attendee_ids])
    Attendee.find_all_by_id(rdb[:attendee_ids].smembers)
  end

  def register(attendee)  
    Redis.current.multi do
      rdb[:attendee_ids].sadd(attendee.id)
      attendee.rdb[:conference_ids].sadd id
    end
  end

  def unregister(attendee)
    Redis.current.multi do
      rdb[:attendee_ids].srem(attendee.id)
      attendee.rdb[:conference_ids].srem id
    end
  end

end

私が次のようなことをした場合

conferences = Conference.first(20)
conferences.each {|c|
    c.attendees.each {|a| puts a.name}
}

最初の20の会議を取得し、それぞれに参加者を取得して印刷しているだけですが、ビュー内のリストに参加者のリストとともに会議をレンダリングしている場合を想像できます。上記の場合、私は古典的なN+1クエリの問題に遭遇するでしょう。

と一緒にSQLで関係をモデル化した場合、同じ問題を回避するために関数をhas_many使用できたはずです。includes

アイデア、リンク、質問を歓迎します。

4

1 に答える 1

1

Redisはアプリケーションのインフラストラクチャに大きなメリットをもたらしますが、さまざまなデータタイプで実行できる特定の操作のために、アクセス方法を事前に検討する必要があることがわかりました。データ。この例では、多数の会議を繰り返して参加者を出力することが非常に多く、Redisの豊富なセット操作(交差点、ユニオンなど)を実行する機能の恩恵を受けていない場合は、適切ではない可能性があります。そのデータモデルに適合します。

一方、アプリケーションのパフォーマンスを重視する部分でRedisのメリットを享受している場合、それらのメリットを享受するために、RedisでN +1GETをときどき食べる価値があるかもしれません。トレードオフに値するかどうかを確認するには、気になるアプリの部分でプロファイリングを行う必要があります。

また、N + 1 GETを回避できるように、Redis/アプリケーションでデータを構造化できる場合があります。たとえば、すべてのキーを事前に取得できる場合は、MGETを使用してすべてのキーを一度に取得できます。これは高速なO(N)操作であり、パイプラインを使用して複数のルックアップのネットワーク遅延を回避できます。

私が取り組んでいるアプリケーションでは、has_many関係の外部キーIDをキャッシュするキャッシングレイヤーを構築しました。これにより、相互に複雑な関係を持つモデルの大規模なセットのキャッシュバージョンを高速に検索できます。これらをSQLでフェッチしている間、非常に大きく、比較的遅いSQLクエリを生成しますが、Redisとキャッシュされた外部キーを使用することで、データベースにまったくアクセスせずにいくつかのMGETを実行できます。ただし、ボトルネックがどこにあるかを調査し、それらを回避する方法について話し合うことによってのみ、その解決策に到達しました。

于 2012-11-29T09:38:29.363 に答える