2010-03-17 26 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