2016-04-18 12 views
0

はのは、次の関係(3モデル)を考えてみましょう:will_many:RoRに大きなパフォーマンス上の影響を与えますか?

class Author < ActiveRecord::Base 
    has_many :authorships 
    has_many :papers, :through => :authorships 
end 
class Paper < ActiveRecord::Base 
    has_many :authorships, inverse_of: :paper, :dependent => :destroy 
    has_many :authors, :through => :authorships 
    accepts_nested_attributes_for :authorships, :allow_destroy => true 
end 
class Authorship < ActiveRecord::Base 
    belongs_to :paper 
    belongs_to :author 
    validate: rank, presence: true # position of the author 
end 

あなたが見ることができるように、私はたくさんhas_manyを使用しても:through。基本的にすべての論文とそれに対応する著者を表示するpaper.html.erbページを閲覧すると、システムが大きく遅くなる。今私は約400の論文と2000人の著者を持っており、ページをロードするのに3秒かかります。さらに、RoRがたくさんのSQLクエリを作ったのを見たログから、クエリの大部分が著者を検索しています。私はこれがRoRの典型的なものであると思っていました。ご協力いただきありがとうございます。

+0

コントローラとビューコードも投稿できますか? –

答えて

2

これは、最適化の問題のように聞こえます。あなたの元の質問に答えるために、has_many:それだけでは大きな違いはありません。 PaperAuthorshipの2つのテーブルしかない場合は、全く同じ問題が発生します。

あなたのログについて報告した内容に基づいて、私はあなたのコードは次のようになりますと仮定します。

あなたが paper.authorsを呼び出すたびのために、それが関連する著者を取得するためにクエリを実行しますされない何レール
# Controller: 
@papers = Paper.all 

# View: 
<% @papers.each do |paper| %> 
    <%= paper.authors.join(', ') %> 
    <%# other code... %> 
<% end %> 

その論文と一緒にあなたが400の論文を持っているなら、レールは400のクエリを実行します。これは、最初のレコードを取得するための最初のクエリとともに、n個のクエリが各レコードに対して実行されるn + 1クエリ問題と呼ばれます。 Railsには、この問題に対処するための素晴らしいガイドがあります。http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations

基本的には、論文の著者を取得するたびにクエリを実行しないようにします。代わりに、次のようにコントローラに論文を読み込むことができます:@papers = Paper.includes(:author).all。これにより、関連する著者と一緒にすべての論文が読み込まれ、2つのクエリのみが実行されます.1つはすべての論文、もう1つはすべての論文の著者です。

しかし、あまりにも多くのレコードがあると、読み込み時間が遅くなる可能性があるので、.includesを酷使することに注意してください。 RailsはそれぞれPaperと各Authorオブジェクトを作成するのに時間がかかります。現在、データベースレコードに基づいて2,400個のオブジェクトを作成しています。一定数のレコードを取得した後は、1ページに数万のレコードをロードするのではなく、ページ番号または検索機能を追加する必要があります。

+0

私はあなたが意味するように思っています。作者ですが、それはスピードアップします! – TimeString

関連する問題