2010-03-17 27 views
1

我有三个模型,看起来像这样:可怜的Ruby on Rails的性能:包括

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}) 

为什么第二个命令与第一个命令相比会有如此糟糕的表现?

+0

只是为了澄清:您直接执行查询,因为它们出现在您的development.log中? – 2010-03-18 02:56:34

+0

是的,我完全按照它们出现在开发日志中那样添加了查询。看起来这可能是一个对象序列化/反序列化问题,因为视图需要28秒才能在用户包含的情况下运行。 – 2010-03-18 17:43:16

回答

0

这结束了在整个对象图形用户模型的序列化/反序列化的问题。通过在入口和提交模型上缓存相关数据,我们可以避免查找用户并节省大量时间。

0

这是因为你在第二个语句中有一个双连接。所以结果的数量更大。

更大的结果是很慢的。

+0

是的,但Ruby on Rails在使用include语句时实际上并不使用INNER JOIN。相反,它会为查询的每个级别发出多个选择语句。该行为在2.0中发生了变化 – 2010-03-18 00:04:39

0

我不知道如果表现会好很多,但尝试:

@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