代码之家  ›  专栏  ›  技术社区  ›  Jeremiah Peschka

使用嵌套时ruby on rails性能不佳:include

  •  1
  • Jeremiah Peschka  · 技术社区  · 15 年前

    我有三个这样的模型:

    class Bucket < ActiveRecord::Base
      has_many :entries
    end
    
    class Entry < ActiveRecord::Base
      belongs_to :submission
      belongs_to :bucket
    end
    
    class Submission < ActiveRecord::Base
      has_many :entries
      belongs_to :user
    end
    
    class User < ActiveRecord::Base
       has_many :submissions
    end
    

    当我检索一组条目时,执行以下操作:

    @entries = Entry.find(:all,
                          :conditions => ['entries.bucket_id = ?', @bucket],
                          :include    => :submission)
    

    虽然由于视图使用submission.user对象,我得到了大量额外的查询,但是性能相当快。但是,如果我将用户添加到:include语句中,性能会变得很糟糕,返回总共50个条目和分布在5个用户中的提交需要一分钟的时间。当我运行相关联的sql命令时,它们在一秒钟内就完成了——每组查询的sql查询性能是相同的。

    @entries = Entry.find(:all,
                          :conditions => ['entries.bucket_id = ?', @bucket],
                          :include    => {:submission => :user})
    

    为什么这第二个指挥部的表现会比第一个糟糕?

    3 回复  |  直到 15 年前
        1
  •  0
  •   shingara    15 年前

    因为在第二个语句中有一个双联接。所以结果的数目更大。

    越大的结果就越慢。

        2
  •  0
  •   Peter Brown    15 年前

    我不确定表演是否会更好,但请尝试:

    @bucket.entries.find(:all, :include => {:submission => :user})
    

    我真的只熟悉mysql,但是如果您的数据库支持它们,索引将大大提高性能。在我的迁移过程中,我通常会这样做:

    def self.up
      create_table :entries do |t|
        t.references :submission 
        t.references :bucket
        # other fields...
      end
    
      add_index :entries, :submission_id
      add_index :entries, :bucket_id
    end
    
        3
  •  0
  •   Jeremiah Peschka    15 年前

    这最终导致整个对象图中用户模型的序列化/反序列化出现问题。通过缓存条目和提交模型上的相关数据,我们能够避免对用户的查找,并节省了大量时间。

    推荐文章