2012-08-29 49 views
1

我試圖首次在活動記錄中優化一些N + 1查詢。有3個要殺 - 2個很容易用.includes調用,但我不能爲了我的生活找出爲什麼第三個仍在調用一堆查詢。下面的相關代碼 - 如果有人有任何建議,我會非常感激。Rails - >不會消失的n + 1數據庫問題

CONTROLLER:

@enquiries = Comment.includes(:children).faqs_for_project(@project) 

模型;

def self.faqs_for_project(project) 
    Comment.for_project_and_enquiries(project, project.enquiries).where(:published => true).order("created_at DESC") 
end 

(以及相關的範圍)

scope :for_project_and_enquiries, lambda{|p, qs| where('(commentable_type = ? and commentable_id = ?) or (commentable_type = ? and commentable_id IN (?))', "Project", p.id, "Enquiry", qs.collect{|q| q.id})} 

VIEW:

... 
= render :partial => 'comments/comment', :collection => @enquries 
... 

(以及部分該問題的行)

... 
= 'Read by ' + pluralize(comment.acknowledgers.count, 'lead') 
... 

兩個SQL查詢被稱爲爲每個評論。 2.查詢是:

SQL (2.8ms) SELECT COUNT(*) FROM "users" INNER JOIN "acknowledgements" ON "users".id = "acknowledgements".user_id WHERE (("acknowledgements".feedback_type = 'Comment') AND ("acknowledgements".feedback_id = 177621)) 
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1295 LIMIT 1 

我還以爲追加(:用戶:確認)到控制器的.includes就已經解決了這個問題,但它似乎沒有任何效果。如果任何人有我缺少什麼,我有什麼建議,我會非常感激

+0

爲什麼你包括如果你正在調用類方法? –

回答

3

我相信你Comment表要添加一個:acknowledgers_count列作爲計數器緩存

has_many :acknowledgers, ....., counter_cache: true 

您需要創建遷移以將:acknowledgers_count列添加到comments表。其餘的應該由Rails來完成。

您可以瞭解更多關於ActiveRecord::CounterCache api的信息here

comment.acknowledgers.countcount方法在ActiveRecord的重載以首先檢查是否一個計數器緩存列中存在,並且如果是這樣,它返回直接從模型(在這種情況下Comment模型),而無需觸碰數據庫再次。

最後,最近有一個很棒的Railscast關於寶石電話Bullet,可以幫助您識別這些查詢問題並指導您尋找解決方案。它涵蓋了計數器緩存和N + 1個查詢。

正如@ismaelga在對此答案的評論中指出的,在關係上調用.size而不是.count通常是更好的做法。退房the sourcesize

def size 
    loaded? ? @records.length : count 
end 

如果關係已經加載它只會調用它的length,否則它會調用count。這是一個額外的檢查,試圖防止不必要地查詢數據庫。

+1

和通話大小而不是計數 –

+0

非常棒 - 非常感謝。 (有趣的是,切換到.size使得:承認者包括工作......現在有意義;我的不好) – PlankTon