2009-07-19 61 views
2

我只是找了EveryBlock的源代碼,我發現這個代碼在警報/ models.py代碼:Django中的屬性緩存 - 有什麼意義?

def _get_user(self): 
    if not hasattr(self, '_user_cache'): 
     from ebpub.accounts.models import User 
     try: 
      self._user_cache = User.objects.get(id=self.user_id) 
     except User.DoesNotExist: 
      self._user_cache = None 
    return self._user_cache 
    user = property(_get_user) 

我注意到周圍一堆這種模式,但我不太明白使用。整個想法是確保在自己訪問FK(self = alert對象)時,你只需從db中獲取一次用戶對象?爲什麼你不只是依靠db緩存和django的ForeignKey()字段?我注意到模型定義只包含用戶標識而不包含外鍵字段:

class EmailAlert(models.Model): 
    user_id = models.IntegerField() 
    ... 

任何見解將不勝感激。

回答

2

我不知道爲什麼這是一個IntegerField;它看起來肯定應該是一個ForeignKey(用戶)字段 - 因爲這個原因,你在這裏丟失了諸如select_related()之類的東西。對於緩存,許多數據庫不會緩存結果 - 它們(或者說,操作系統)會將數據緩存到獲取結果所需的磁盤上,因此再次查找它應該比首先,但它仍然需要工作。

它仍然需要數據庫往返查看它。根據我的經驗,使用Django時,執行項目查找可能需要大約0.5到1毫秒的時間,對於本地Postgresql服務器的SQL命令以及QuerySet的偶爾開銷。如果你不需要它的話,1ms是很多的 - 這麼做幾次,你可以把一個30ms的請求變成一個35ms的請求。

如果您的SQL服務器不是本地的,並且您實際上有網絡往返處理,則數字會變大。

最後,人們通常期望訪問一個屬性是快速的;當它們足夠複雜導致SQL查詢時,緩存結果通常是一個好主意。

2

雖然數據庫在內部緩存內容,但每當您想要檢查相關字段的值時,仍然會返回數據庫的開銷 - 在Django中設置查詢,連接到數據庫的網絡延遲以及通過網絡返回數據,在Django中實例化對象等。如果您知道數據在此期間沒有改變 - 並且在單個Web請求的上下文中,您可能不在乎它是否有效 - 它會使得很多更有意義獲取數據並緩存它,而不是每次查詢它。

我工作的應用程序中有一個包含大量數據的非常複雜的主頁。以前它正在執行超過400分貝的查詢來渲染。我現在已經對它進行了重構,因此它只使用了80個,使用了與您發佈的技術非常類似的技術,並且您最好相信它會大幅提升性能。