2011-12-19 95 views
2

我正在與很大的mysql2數據庫在此刻工作了很多,雖然我已經索引了我認爲是合適的字段,但某些查詢的返回時間非常緩慢。Rails數據庫性能調優

我有兩個型號導致問題,CommentCommenter

現在,CommenterComment之間存在has_many關係,但我的查詢依賴於查找每個評論的評論者的用戶名。所以,我會跑是這樣的:

c = Blog.first.comments ##this bit runs fine, I indexed the "blog_id" field on Comments 
c.collect {|c| c.commenter.username} 

爲了幫助與速度問題,我創建了用於評價模型commenter_id領域的指標。但它仍然運行非常緩慢..

有人知道我可以做什麼不同,這將有助於提高查詢的速度?

回答

0

我想通了用渴望的負載,這是不RaskolnikOFF發佈的鏈接,但在此之前它的軌道鑄造,http://railscasts.com/episodes/22-eager-loading(還是給你一個給予好評的駕駛我的答案)

顯然我正在尋找的是以下內容:

b = Blog.find(:first, :include=>{:comments => :commenter}) 
b.comments.collect {|c| c.commenter.username} 

第一行加載第一個博客及其所有關係(並返回博客)。所以當我打電話給第二條線時,一切都已經加載並且正在等待被訪問..

這比我原本做的更好。

3

commenter_id上的索引有助於您在查找給定的commenter_id(「找到我所有的評論joe made」)的評論。

但是當你做c.commenter你正在尋找的用戶,可能是id等於評論的commenter_id的用戶。應該已經有id列的索引。在正確的方式是採取實際生成的SQL語句(在發展這些都是development.log),並利用他們解釋,例如

explain select * from comments where id = 12345 

鑑於這是非常不可能的,你成功地創建一個表而不它的指數是id列,最有可能的罪魁禍首是預先加載 - 如果一個職位有500個評論,那麼上面的代碼將獲取相關聯的用戶一個接一個,和那些500次往返於數據庫中添加了

c.includes(:commenter).collect {...} 

c.eager_load(:commenter).collect {...} 

將解決這個問題(上面的代碼片段假定您使用的是rails 3)。

+0

我相信eager_load並且包含僅用於活動記錄關係的工作。不是數組,在我的文章中,c是一個數組。 – BananaNeil 2011-12-20 02:40:05

+0

它實際上並不是 - 關聯就是關係 - 你絕對可以做filtered_ordered_comments = some_blog.comments.where(...)。order(...)例如 – 2011-12-20 08:05:40

2

Collect將爲每個評論者加載ActiveRecord對象,每個評論者一次只填寫一個字段。包括/ Eager Loading會加載一個查詢,這將有助於提高速度,但是如果您希望獲得絕對最佳的性能,並且只需要名稱,則最好直接與SQL進行比較:

c   = Blog.first.comments 
user_ids = c.collect(&:commenter_id) 
usernames = Commenter.where(['commenter_id IN (?)',user_ids]).select('username').collect(&:username)