2

この質問は少し具体的かもしれませんが、一般的な視点からも興味深いと思います。

Rails アプリでは、ユーザーは他のユーザーにサブスクライブできます。現在のユーザーがリスト内のユーザーにサブスクライブしているかどうかを確認する必要があるユーザーのリストを表示するとき。彼が購読している場合は、購読解除ボタンを表示し、その逆です。

全体が現在のユーザーに依存するため、熱心な読み込みは使用できません。したがって、リストに 20 人のユーザーを表示すると、DB で 20 の追加ヒットが生成されます。これは悪い習慣のように思えます。

この問題を解決する良い方法を考えています。私がこれまでに思いついた最善の解決策は、ログイン中に current_user がセッションでサブスクライブしたユーザーの ID をロードし、セッションの ID に対してすべての user.id をチェックすることです。しかし、ユーザーが多くの人にサブスクライブしている場合、これは他の問題につながる可能性があります. また、ユーザーがこのセッション中にユーザー リストをまったく見ない場合でも、すべてのサブスクリプションを読み込むのが最善の方法かどうかはわかりません。

私の頭に浮かんだ次善の策は、同じことをすることでしたが、ログイン中ではなく、代わりにユーザーリストがロードされたときに行いました。

どう思いますか?

4

2 に答える 2

4

必ずキャッシュ システムの作業を開始する必要があります。少なくとも 3 つの方法があります。また、それらを組み合わせて効率を高めることもできます。

データベースのキャッシング

その場で計算する必要がないように、ユーザーとサブスクライバー間の ID 関係を保持する関係テーブルを作成します。

モデルのキャッシング

高価なクエリをキャッシュできます。

def find_subscribers
  Rails.cache.fetch("find_subscribers_#{current_user}") do
    # run the query
  end
end

キャッシングの表示

ビュー フラグメントをキャッシュして、コストのかかる精緻化を防ぐこともできます。

あなたはから始めたいと思うかもしれません:

編集:

クエリを最適化できます。

ActiveRecord::Base.connection.execute("SELECT count(*) as c FROM subscribers_users WHERE user_id = #{other_user.id} AND subscriber_id = #{self.id}") 

になることができる

counters = SubscribersUser.count(:conditions => { :subscriber_id => self.id }, :group => "user_id")

クエリは、キーが user_id であり、値が count の結果であるハッシュを返します。次に、ビュー内の任意のレコードに対してクエリを実行する代わりに、ハッシュを反復できます。

于 2009-06-26T10:27:52.767 に答える
2

熱心な読み込みを使用できる場合、現在のユーザーを再読み込みすることに対するルールはありません。

user = User.find(current_user.id, :include => :subscribers)

これが単純な has_many リレーションである場合、これは 2 つの SQL ステートメントのみです。

これで、別の DB ヒットを生成することなく、user.subscribers を反復処理できます。

于 2009-06-26T17:37:05.933 に答える