2009-07-19 58 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个,使用了与您发布的技术非常类似的技术,并且您最好相信它会大幅提升性能。