2011-12-19 12 views
2

私は現時点で非常に大きなmysql2データベースで多くの作業をしていますが、適切なフィールドだと思ったインデックスを作成しましたが、いくつかのクエリの戻り時間は非常に遅いです。Railsデータベースのパフォーマンスチューニング

問題の原因となるモデルは、CommentCommenterです。

CommenterCommentの間にhas_manyの関係がありますが、私のクエリは各コメントのコメント欄のユーザー名を見つけることに依存しています。だから私はこのような何かを実行します:

c = Blog.first.comments ##this bit runs fine, I indexed the "blog_id" field on Comments 
c.collect {|c| c.commenter.username} 

はスピードの問題を支援するために、私はコメントモデルのcommenter_idフィールドにインデックスを作成しました。しかし、それはまだ非常に遅いです..

私は別のことができるか知っていますか?それはクエリの速度を向上させるのに役立ちますか?

答えて

0

私はどうやら何I

(まだあなたの答えに私を駆動するためupvoteを与えた)RaskolnikOFFが掲載さが、その前にレールがキャスト、http://railscasts.com/episodes/22-eager-loadingリンクされていない、熱心な負荷を使用してそれを考え出しました次のものが検索されました:

b = Blog.find(:first, :include=>{:comments => :commenter}) 
b.comments.collect {|c| c.commenter.username} 

最初の行は、最初のブログとそのすべての関係を読み込み(そしてブログを返します)。だから、私が2行目を呼び出すと、すべてが既に読み込まれており、アクセスするのを待っている。

これは元々やっていたよりもうまくいく。

3

commenter_idのコメントを見つけたいときは、commenter_idのインデックスが役立ちます(「joe madeすべてのコメントを見つける」)。

c.commenterを実行すると、おそらくidがコメントのcommenter_idに等しいユーザーを検索しています。 id列にはすでに索引があるはずです。確実な方法は

explain select * from comments where id = 12345 

が、それはあなたがすることなく、テーブルを作成するために管理することを非常に低いということを考えると、たとえば、(開発中で、これらはdevelopment.logである)生成された実際のSQL文を取り、それらに説明使用することですポストは500件のコメントがあったならば、上記のコードは、関連するユーザーを一つずつフェッチだろう、とデータベースへのそれらの500の往復は

c.includes(:commenter).collect {...} 

を追加 - その上にインデックスがid列ですが、最も可能性の高い犯人は熱心なロードですまたは

c.eager_load(:commenter).collect {...} 

これを修正します(上記のコードでは、レール3を使用していると仮定しています)。

+0

私はeager_loadと考えており、アクティブなレコード関係のみの作業が含まれています。配列ではなく、私のポストでは、cは配列です。 – BananaNeil

+0

これは実際には関係ではありません - 関係は関係です - あなたは間違いなくfiltered_ordered_comments = some_blog.comments.where(...)。order(...)などを行うことができます –

2

Collectは、すべてのフィールドが1つずつあるすべてのコメント投稿者のActiveRecordオブジェクトを1つずつ読み込みます。インクルード/エイジャーローディングでは、スピードに役立つ1つのクエリがロードされますが、最高のパフォーマンスが絶対に必要な場合は、名前を必要とするだけで、より正確にSQLに到達する方が良いでしょう。

c   = Blog.first.comments 
user_ids = c.collect(&:commenter_id) 
usernames = Commenter.where(['commenter_id IN (?)',user_ids]).select('username').collect(&:username) 
関連する問題