2009-06-26 52 views
2

這個問題可能有點特定,但我認爲它也是一個普通的pov有趣。Rails:如何最小化數據庫匹配?急於加載不適用

在Rails App中,用戶可以訂閱其他用戶。當我顯示一個用戶列表時,我必須檢查,如果當前用戶已經訂閱了列表中的用戶。如果他訂閱了,我會顯示取消訂閱按鈕和其他方式。

因爲整個事情取決於當前用戶我不能使用急切加載。所以當我在列表中顯示20個用戶時,我在數據庫上生成了20個額外的點擊,這在我看來是不好的練習。

我在想一個解決這個問題的好方法。到目前爲止,我提出的最佳解決方案是在登錄期間加載current_user在會話中訂閱的用戶的id,然後僅檢查每個user.id與會話中的id。但是,當用戶訂閱了很多人時,這可能會導致其他問題。此外,我不確定是否加載所有訂閱的最佳方式,即使用戶在此會話期間可能永遠不會查看用戶列表。

我想到的下一件最好的事情是做同樣的事情,但不是在登錄時,而是在加載用戶列表時。

您認爲如何?

回答

4

你應該開始研究緩存系統。至少有3種方法可以關注。您也可以將它們組合起來以獲得更高的效率。

數據庫緩存

創建關係表來保存用戶與用戶之間的關係,ID,這樣你就不需要計算它們的飛行。

型號緩存

昂貴的查詢可以被緩存。

def find_subscribers 
    Rails.cache.fetch("find_subscribers_#{current_user}") do 
    # run the query 
    end 
end 

查看緩存

您還可以查看緩存片段,以避免昂貴的闡述。

您可能要開始:

編輯:

您查詢可以得到優化。

ActiveRecord::Base.connection.execute("SELECT count(*) as c FROM subscribers_users WHERE user_id = #{other_user.id} AND subscriber_id = #{self.id}") 

可以成爲

counters = SubscribersUser.count(:conditions => { :subscriber_id => self.id }, :group => "user_id") 

查詢將返回一個散列結果,其中的關鍵是USER_ID和計數的結果值。然後,您可以迭代散列,而不是對視圖中的任何記錄運行查詢。

+0

謝謝,我已經有一個關係表,到目前爲止我的查詢並不昂貴。它只是執行一個awfull很多: ActiveRecord :: Base.connection.execute(「SELECT count(*)as c FROM subscribers_users WHERE user_id =#{other_user.id} AND subscriber_id =#{self.id}」) 但據我瞭解,我應該讓所有訂閱者進行一個查詢並緩存結果。正確? – 2009-06-26 11:31:23

2

有反對重新加載當前用戶,如果它允許您使用預先加載任何規則:

用戶= User.find(current_user.id,:包括=>:用戶)

提供,這是一個簡單的has_many關係這隻有2個SQL語句。

現在你可以迭代user.subscribers而不會產生另一個數據庫命中。