我有三个看起来像这样的模型:
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 :(得分:0)
这是因为你在第二个语句中有一个双连接。所以结果的数量更大。
结果越大,结果就越慢。
答案 1 :(得分: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
答案 2 :(得分:0)
这最终成为整个对象图中用户模型的序列化/反序列化的问题。通过在Entry和Submission模型上缓存相关数据,我们可以避免查找User并节省了大量时间。