2

大規模なプロジェクトですべてのクエリを実行して、すべてのオブジェクトの関連付けを熱心にロードするのは、どの時点で適切ですか?
この質問の背景を説明しましょう。
現在、モデルと関連付けの点で非常に複雑になっているプロジェクトに取り組んでいます。サーバーログの確認を開始したところ、クエリにネストされたオブジェクトが含まれているため、一部のビューの読み込みに時間がかかっていることがわかりました。
だから私はこれらのクエリのいくつかを次のようなものにリファクタリングし始めます:

@process = current_account.processes.query(params)

これに:

@process = current_account.processes.includes(:messages, :parts, :people).query(params)

結果はかなり良かった。一部のビューでは、ビューのレンダリング時間とactiverecordのクエリ時間を70%短縮できました。
男は幸せだったので、もっと作ることにしました。しかし、この決定の後、コードをリファクタリングしたすべての場所ではなく、変更が適切であることに気付き始めました。実際、遅くなったクエリがありました。
問題についてもう少し説明するために、私はこのようなモデルを持っています:

class Process
  has_many :anotations
  has_many :publications
  has_many :movimentations
  has_many :reunions
  has_many :profiles
  ...

そして、その中のこれらのネストされたモデルのそれぞれは、次のprocess belongs_to :userようにそれを作成しました:

class Anotation
  belongs_to :user

class Reunion
  belongs_to :user

class Profile
  belongs_to :user

そしてそれは続く。
show viewのには、これらのネストされたオブジェクトのすべてと、それを現在のプロセスに追加したユーザーの名前をprocess表示するいくつかのタブがあります。 このようなクエリで:

@process = current_account.processes.query(params)

パフォーマンスが少し遅いです。だから私はこのようなことを試みました:

@process = current_account.process.includes(:anotations, :publications, :movimentations, 
  :reunions, :profiles, :messages).query(params)

これにより、ビューレンダリングの速度が向上しましたが、activerecordでは、これらのオブジェクトを取得する時間が大幅に増加しました。userそして、私がこのようなすべてのネストされたモデルの中にオブジェクトを熱心にロードしたとき、それは空に上がりましたprocess

@process = current_account.process.includes({:anotations => [:user]}, 
  {:publications => [:user], etc...).query(params)

さて、これらの関連付けで異なる動作をするようにアプリのデザインをリファクタリングすることは起こらないので、もう一度質問します。
大規模なプロジェクトですべてのクエリを実行して、すべてのオブジェクトの関連付けを熱心にロードするのは、どの時点で適切ですか?
このテーマに関するヒント/ベストプラクティス/経験をいただければ幸いです。

4

1 に答える 1

1

「すべてのオブジェクトの関連付けを熱心にロードするための大規模なプロジェクトに対するすべてのクエリ」-ほとんどありません。少なくとも、アプリケーション内のヘルプなしではありません。

私があなたの立場にあったら、私はキャッシングを検討し始めました(あなたが言及しなかったので、あなたが何かをしているのかどうかはわかりません)。特にフラグメントキャッシングは、タブ構造にうまく適合しているように見えるためです。

あるアプリでは、コンテキスト依存のサイドバーを使用して、アイテムのグループのリストを表示しました。各グループには関連アイテムへのリンクが含まれ(18グループのいずれかでn個のアイテム)、各アイテムにはリンクフォームに関連アイテムの名前が表示されます(および他のいくつかの小さなデータ項目)。

サイドバーの各グループがキャッシュされ、そのグループの各関連アイテムのエントリもキャッシュされました。コントローラは、関連アイテムを@relatedとして蓄積するようにリファクタリングし、そのコードはキャッシュを利用して、フェッチが必要かどうかを判断しました(キャッシュミスの場合)。インテリジェントキャッシュの有効期限に少し手を加えるだけで、パフォーマンスは非常に良好でした。

プロジェクトXに、12のカテゴリ(120の関連アイテム)のそれぞれに10の関連アイテムがあるとします。プロジェクトXの最初のショーでは、代金を支払います。カテゴリ内の1つの関連アイテムの名前を変更すると、そのアイテム、そのアイテムのグループ、およびサイドバー全体のキャッシュが無効になります。プロジェクトXの次のショーでは、サイドバーの再構築で1つのアイテムに対して1つのキャッシュミスが発生し(1つまたは2つの結合でそのアイテムのレコードを読み取る)、アイテムキャッシュが再構築され、1つのカテゴリキャッシュが10のアイテムキャッシュから再構築されました(1新規+9既存)、他の11カテゴリのキャッシュヒット(これらの110の関連アイテムを読み取っていない)、および最後に再構築されたサイドバーキャッシュを生成しました。

タブにも同様の戦略を採用できるように感じますが、それはおそらくよりきめ細かいものですが、それは実装次第です。

于 2012-07-30T16:49:18.970 に答える