2013-03-01 50 views
0

這有點奇怪。鐵軌中的奇怪行爲;重寫的有效記錄/視圖代碼位意外地花費更長的時間運行不少於時間

在導軌中我有頁面有時需要一段時間才能加載(大約12秒)。所以,我嘗試過這麼大的部分用於緩存的查詢,而不是找他們協會的重新寫,我會在下面解釋:

示例代碼之前,我試圖加快速度:

假設每個用戶都屬於一個帳戶,所以在它看起來像這樣

class User < ActiveRecord::Base 
belongs_to :account 
end 

class Account < ActiveRecord::Base 
end 

的觀點:

@users = User.all 

<% @users.each do | user | %> 
    <%= user.account.name %> 
<% end %> 

這在日誌中會導致爲每個用戶/帳戶ASSO各個查詢ciation。所以會有100查詢的,看起來是這樣的:

select * from accounts where account.id = 1; 

因此,當每個用戶的帳戶被擡起頭來,一個人通過查詢從用戶的ACCOUNT_ID一個發現擡頭的帳戶。

我試圖通過一個查詢查找所有的帳戶,以加快該頁面後,通過和IN()入手,然後檢測他們在需要的時候,像這樣:

在Rails應用程序有此代碼現在:

@users = User.all 
@all_accounts = Account.where(:id => users.map{ | user | user.account_id }) 

<% @users.each do | user | %> 
    <%= @all_accounts.detect{ | a | a.id == user.account_id }.name %> 
<% end %> 

這意味着每行調用一次緩存查詢,即花費0秒運行而不是100個單獨的選擇。

這是這一切變得很奇怪...

在第一個例子中,頁面渲染的活動記錄部分大約需要6000ms和視圖部分需要大約6000ms。所以大概12秒鐘,這是垃圾。

我期待重新編寫代碼,其中的檢測速度更快,但是頁面上的活動記錄部分渲染速度超過1000毫秒(一秒),視圖部分花費大約30秒!

這到底是怎麼回事?視圖如何花費大約半分鐘時間來呈現?

讓我們假設頁面不能分頁,根據客戶端請求。而且它也不能有無限滾動,整個頁面需要被渲染得更快。很明顯,我也可以使用內建在rails中的memcaching,但我們假設這不是一個選項。而且它在memcached之前第一次渲染時仍然需要加載。

那麼爲什麼它在視圖中花了這麼長時間?任何在景點將非常感謝!謝謝!

+0

爲什麼不在用戶查詢中設置:include?它的作用就像你在@all_accounts上的小補丁... http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html – pierallard 2013-03-01 11:38:57

回答

3

您可以使用rails默認機制在查詢中包含關聯。 此外,您應該在遍歷大型數據集時使用find_each。它獲取分批對象,從而保險箱內存:

@users = User.includes(:account) 

<% @users.find_each do | user | %> 
    <%= user.account.name %> 
<% end %> 
1

它服用的年齡,因爲@all_accounts = Account.where(:id => users.map{ | user | user.account_id })並不實際運行該查詢。查詢在實際需要時運行,即當您撥打detect時。

它正在爲每個用戶運行Account查詢,這顯然是一個比你原來的查詢更大的查詢,因爲它每次都會拖拉Account秒,因此等待很長時間。

解決方案顯然是做了別人推薦什麼,並用includes,但你Account的查詢的粘底.all可能通過使該查詢在第一時間執行工作了。

相關問題